David Cordero

CMTime for Human Beings

Published on 07 Jul 2021

CMTime is a struct representing a time value such as a timestamp or duration. CMTime is defined by CoreMedia and it is often used by AVFoundation API interfaces.

Because the interface of CMTime is horrible, and its documentation is even worse, here you have a few use cases to make it easier to work with CMTime in a daily basis.

Create a CMTime

Apart from its initializers, a CMTime is often created with the function CMTimeMake.

CMTimeMake(value: timescale:)

This function creates a CMTime with a duration of value/timescale seconds.

Examples:

CMTimeMake(value: 1, timescale: 1) // 1 second
CMTimeMake(value: 1, timescale: 2) // 0.5 seconds
CMTimeMake(value: 2000, timescale: 1000) // 2 seconds
CMTimeMake(value: 2000, timescale: 3000) // 0.6666666 seconds

Get value from CMTime

CMTime has a value property, but because its actual value depends on the timescale of the CMTime, it is not very useful in daily basis. Instead it is usually better to use CMTimeGetSeconds.

CMTimeGetSeconds

CMTimeGetSeconds is a function that returns a float value representing a CMTime in seconds.

Example 1:

let time = CMTimeMake(value: 2000, timescale: 1000)
let seconds = CMTimeGetSeconds(time)
print(seconds) // 2.0

Example 2:

let time = CMTimeMake(value: 1, timescale: 5)
let seconds = CMTimeGetSeconds(time)
print(seconds) // 0.2

Property seconds

As a syntax sugar 🍭 you can also get the seconds from a CMTime value from the property seconds of CMTime.

let secondsWithCMTimeGetSeconds = CMTimeGetSeconds(time)
let secondsWithSyntaxSugar = time.seconds
print(secondsWithCMTimeGetSeconds == secondsWithSyntaxSugar) // true

All it says is No overview available., but here you have the documentation from Apple as a “reference”:

https://developer.apple.com/documentation/coremedia/cmtime/1489443-seconds

CMTime fun values

Apart from the numerical values that one could expect from CMTime. It can also take other fun values such as NaN (Not a Number) or Infinite.

The function isFinite can be useful to deal with these cases.

You can find here below an example of this use case. Contrary to expected, the following code will print NaN, even though time has no value. This is because the fallback string is never used because of time.seconds does not return nil but NaN.

let time = CMTime()
print(time.seconds ?? "I'm sorry but I do not have any value for you")

Here you can see how we can use the function isFinite to deal with this problem:

let time = CMTime()
let seconds = time.seconds
print(seconds.isFinite ? seconds : "I'm sorry but I do not have any value for you")