问题
I am working on CMTimeMake in order to add slow and fast motion effect to Video. Where we have to divide by Video scale for Fast effect and multiply by Video scale for Slow effect.
Here it is:
let videoScaleFactor = Int64(2)
// Get the scaled video duration
let scaledVideoDuration = (mode == .Faster) ? CMTimeMake(videoAsset.duration.value / videoScaleFactor, videoAsset.duration.timescale) : CMTimeMake(videoAsset.duration.value * videoScaleFactor, videoAsset.duration.timescale)
Now as per my requirement, there is one Slider (between 0.1 to 2.0) where User will select the particular Video scale value for Slow and Fast effect. This Value is coming in Float.
My problem is when I am passing my Float value like 0.8 in my above code, then:
let videoScaleFactor = Int64(0.8) // this returns me 0
How can I return exact value 0.8 into this? Please advise me.
回答1:
You wrote:
let videoScaleFactor = Int64(0.8) // this returns me 0
That's normal, because by definition can't have decimal value. So 0.8 => 0.
Instead use a Float
(or Double
) depending on the precision you need.
So let's try it:
let videoScaleFactor = Float(0.8)
// Get the scaled video duration
let scaledVideoDuration = (mode == .Faster) ? CMTimeMake(videoAsset.duration.value / videoScaleFactor, videoAsset.duration.timescale) : CMTimeMake(videoAsset.duration.value * videoScaleFactor, videoAsset.duration.timescale)
That rises another issue:
Binary operator '/' cannot be applied to operands of type 'CMTimeValue' (aka 'Int64') and 'Float'
Indeed in Swift you can't manipulate various types of Int/Float etc like that.
So to fix it:
let videoScaleFactor = Float(0.8)
// Get the scaled video duration
let scaledVideoDuration = (mode == .Faster) ? CMTimeMake(Float(videoAsset.duration.value) / videoScaleFactor, videoAsset.duration.timescale) : CMTimeMake(Float(videoAsset.duration.value) * videoScaleFactor, videoAsset.duration.timescale)
Now you multiply/divide Float
with other Float
But
func CMTimeMake(_ value: Int64, _ timescale: Int32) -> CMTime
So CMTimeMake(_:_:)
awaits for a Int64
value, so you get an error because Float(videoAsset.duration.value) / videoScaleFactor
(for the first one) is returning a Float
while the method wants an Int64.
So just do
let videoScaleFactor = Float(0.8)
// Get the scaled video duration
let scaledVideoDuration = (mode == .Faster) ? CMTimeMake(Int64(Float(videoAsset.duration.value) / videoScaleFactor), videoAsset.duration.timescale) : CMTimeMake(Int64(Float(videoAsset.duration.value) * videoScaleFactor), videoAsset.duration.timescale)
That should work now.
But I can't leave with that code. Your line is quite long and it's hard to read. In fact, you just modify the value
param of CMTimeMake(_:_:)
.
Let's factorize:
let videoScaleFactor = Float(0.8)
// Get the scaled video duration
let scaledVideoDuration = CMTimeMake((mode == .Faster) ? Int64(Float(videoAsset.duration.value) / videoScaleFactor) : Int64(Float(videoAsset.duration.value) * videoScaleFactor), videoAsset.duration.timescale)
Now, it's personal, by I'd prefer (nothing wrong with an extra line explicit):
let videoScaleFactor = Float(0.8)
let value = (mode == .Faster) ? Float(videoAsset.duration.value) / videoScaleFactor : Float(videoAsset.duration.value) * videoScaleFactor
let scaledVideoDuration = CMTimeMake(Int64(value), videoAsset.duration.timescale)
来源:https://stackoverflow.com/questions/51672908/how-to-pass-float-in-cmtimemakes-timescale-int32