0

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.

rmaddy
  • 314,917
  • 42
  • 532
  • 579
user2786
  • 656
  • 4
  • 13
  • 35
  • Don't use Int64 for `videoScaleFactor`, use a `Float`. – Larme Aug 03 '18 at 13:51
  • I can use, but when I am using Float, it's giving me error like this should be Int64. – user2786 Aug 03 '18 at 13:55
  • Because `CMTimeMake(_:_:)` awaits for an Int64 then a Int32. What you need to do `CMTimeMake(Int64(videoAsset.duration.value / videoScaleFactor), ...)` etc. where `videoScaleFactor` is a `Float`. In other words, use Float/Double or others to do your calculation but then convert to Int64. – Larme Aug 03 '18 at 13:57
  • when I am trying to do like: let videoScaleFactor = Float(0.12) let scaledVideoDuration = (mode == .Faster) ? CMTimeMake(Int64(videoAsset.duration.value / videoScaleFactor), videoAsset.duration.timescale) : CMTimeMake(Int64(videoAsset.duration.value * videoScaleFactor), videoAsset.duration.timescale) then getting error: Binary operator '/' cannot be applied to operands of type 'CMTimeValue' (aka 'Int64') and 'Float' – user2786 Aug 03 '18 at 14:01
  • It it possible to pass directly my Float value? – user2786 Aug 03 '18 at 14:01
  • It's because `videoAsset.duration.value` is a Int64 I guess. Then do `CMTimeMake(Int64(Float(videoAsset.duration.value) / videoScaleFactor),...` – Larme Aug 03 '18 at 14:02
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/177356/discussion-between-user2786-and-larme). – user2786 Aug 03 '18 at 14:03

1 Answers1

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)
Larme
  • 24,190
  • 6
  • 51
  • 81