Converting CMTime To String is wrong value return
You need to round your seconds before calculating your time components.
extension CMTime {
var roundedSeconds: TimeInterval {
return seconds.rounded()
}
var hours: Int { return Int(roundedSeconds / 3600) }
var minute: Int { return Int(roundedSeconds.truncatingRemainder(dividingBy: 3600) / 60) }
var second: Int { return Int(roundedSeconds.truncatingRemainder(dividingBy: 60)) }
var positionalTime: String {
return hours > 0 ?
String(format: "%d:%02d:%02d",
hours, minute, second) :
String(format: "%02d:%02d",
minute, second)
}
}
Testing all the possible edge rounding cases:
CMTime(value: 0, timescale: 600).positionalTime // "00:00"
CMTime(value: 300, timescale: 600).positionalTime // "00:01"
CMTime(value: 600, timescale: 600).positionalTime // "00:01"
CMTime(value: 18000 - 600, timescale: 600).positionalTime // "00:29"
CMTime(value: 17945, timescale: 600).positionalTime // "00:30"
CMTime(value: 18000, timescale: 600).positionalTime // "00:30"
CMTime(value: 18055, timescale: 600).positionalTime // "00:30"
CMTime(value: 18000 + 600, timescale: 600).positionalTime // "00:31"
CMTime(value: 2160000 - 600, timescale: 600).positionalTime // "59:59"
CMTime(value: 2160000 - 300, timescale: 600).positionalTime // "1:00:00"
CMTime(value: 2160000, timescale: 600).positionalTime // "1:00:00"
Converting CMTime values to swift
You can not simply perform mathematically operation with different type of operands in swift like other languages. You need to type-cast manually.
Here you should cast videoAsset.naturalTimeScale
( which is CMTimeScale
and CMTimeScale is of type Int32
) to Float to get it work.
Float(videoAsset.naturalTimeScale)
But CMTimeMake
's value key will accept value CMTimeValue
type value. So use it like:
trimmingTime = CMTimeMake(value: CMTimeValue(Float(videoAsset.naturalTimeScale) / videoAsset.nominalFrameRate), timescale: videoAsset.naturalTimeScale)
Again to make you code more Swifty use CMTime
rather CMTimeMake
as:
trimmingTime = CMTime(value: CMTimeValue(Float(videoAsset.naturalTimeScale) / videoAsset.nominalFrameRate), timescale: videoAsset.naturalTimeScale)
Receiving Fatal error: Double value cannot be converted to Int because it is either infinite or NaN
From the CMTimeGetSeconds
documentation:
If the CMTime is invalid or indefinite, NaN is returned. If the CMTime
is infinite, +/- infinity is returned.
When CMTimeGetSeconds
returns NaN or infinity, casting the return value to an Int
will throw the Fatal Error you are seeing.
You can first check the value then return some sort of default in case it's not a valid number.
func toDisplayString() -> String {
let rawSeconds = CMTimeGetSeconds(self)
guard !(rawSeconds.isNaN || rawSeconds.isInfinite) else {
return "--" // or some other default string
}
let totalSeconds = Int(rawSeconds)
let seconds = totalSeconds % 60
let minutes = totalSeconds / 60
let timeFormatString = String(format: "%02d:%02d", minutes, seconds)
return timeFormatString
}
CMTimeClampToRange() doesn't seem to return a CMTime that's inside the given range
I've worked out the following hack:
clipTime = CMTimeMaximum(clipRange.start, CMTimeSubtract(clipTime, CMTimeMake(1, clipTime.timescale)));
Basically, it subtracts the smallest non-empty timespan within the same timescale from the clamped time and makes sure we don't yield a negative value.
Xcode 6- SWIFT- Cast CMTime as Float
CMTime
is a structure, containing a value
, timescale
and other fields,
so you cannot just "cast" it to a floating point value.
Fortunately, there is a conversion function CMTimeGetSeconds()
:
let cmTime = player.currentTime()
let floatTime = Float(CMTimeGetSeconds(player.currentTime()))
Update: As of Swift 3, player.currentTime
returns aTimeInterval
which is a type alias for Double
.
Therefore the conversion to Float
simplifies to
let floatTime = Float(player.currentTime)
How do I convert a CMTime to an NSValue in Swift?
The Swift constructor corresponding to valueWithCMTime: is NSValue(time:):
import CoreMedia
import AVFoundation
let cmTime = CMTimeMake(value: 10, timescale: 20) // Updated for Swift 3+
let cmValue = NSValue(time: cmTime)
// Or simply:
let cmValue = cmTime as NSValue
CMTime doesn't seek AVPlayer to correct time
Your entire use of CMTime(seconds:preferredTimescale:)
is wrong. The first argument should be a number of seconds (hence the name, seconds:
), not a number of milliseconds; and the second argument should be a reasonable timescale, such as 600.
Related Topics
Is There a Method to Check The UIcollectionview Item Drag Cancellation If The Item Wasn't Moved
Xcode Failed to Resolve Dependency Firebase - Googleappmeasurement Does Not Match Requirement
How to Get .Adjustsfontsizetofitwidth to Function Properly
Why Does Cabasicanimation Try to Initialize Another Instance of My Custom Calayer
Avaudioconverter with Avaudioconverterinputblock Stutters Audio After Processing
Why How to Make Same-Type Requirement in Swift with Generics? Is There Any Way
Navigation Bar Items After Push from Swiftui to UIkit
Nstoolbarflexiblespaceitem Is Constraint to Nssplitviewitem in Swift
Naming Convention for Private Properties
Swift Difference Between Double and Float64
How to Find Realm File Location of a MAC App
Trying to Access Error Code in Alamofire
Swift: Urlsession.Shared.Datatask Says Status Code 304 = 200
Dynamic Dispatching Protocol Extension Doesn't Work Multiple Targets
Cannot Decode Object of Class (Ampathpopupbutton)'
Navigationlink Doesn't Work with New .Searchable Modifier on Swiftui 3.0