alex alex - 4 months ago 96
Swift Question

Swift AVPlayer seekToTime issue

i have this code :

let punto = sender.locationInView(self.barraVideo).x
let larghezzaImg : Double = Double((self.barraVideoInvisTocco?.frame.width)!)

let percTocco : Double = (100 / larghezzaImg) * Double(punto)

let lunghezzaVideo : Double = Double(CGFloat((avPlayer?.currentItem?.asset.duration.value)!) / CGFloat(1000.0));
let frameRate : Int32 = (avPlayer?.currentItem?.currentTime().timescale)!

let secondo : Float64 = Float64((lunghezzaVideo/100)*percTocco)
print("Val : \(secondo)");

avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate))

avPlayer?.play()
videoInPlay = true;
playPauseBtn!.image = UIImage(named: "iconaPausa.png")!;


That recive a x cordinate of a tap on the seekBar and seek the video.
The code works with logs video but work very bad with short videos.
When i tap on the short video the AVPlayer seek only near the begining or near the end of the video, not in the middle

print :

Val : 3.36008475976495
Val : 7.14189817632069
Val : 13.3303201306846
Val : 3.70388597945183
Val : 3.93308679257642
Val : 3.24548435320265
Val : 3.70388597945183
Val : 18.8311396456748
Val : 27.0823689181601
Val : 40.1468152662618
Val : 51.3776551093667
Val : 17.2267339538027
Val : 9.54850671412889
Val : 23.4151559081666
Val : 37.6256063218913


The val rappresents the right value of seconds where i wont to seek.
Sorry for bad english, i'm italian

Answer

For AVPlayer, there are different ways to let the play seeking time;

player.seekToTime(<#time: CMTime#CMTime#>)

for this method,player will seek to seekingTime quickly but not seeking the exactly where the seekingTime is, it means there will be some offset of the seekingTime.

Apple's Doc

Use this method to seek to a specified time for the current player item.

The time seeked to may differ from the specified time for efficiency.

For sample accurate seeking see seekToTime:toleranceBefore:toleranceAfter:.

player.seekToTime(<#T##time: CMTime##CMTime#>, completionHandler: <#T##(Bool) -> Void#>)

for this method,player will seek to seekingTime quickly and also,with the offset,you can do something with completionHandler

Apple's Doc

Use this method to seek to a specified time for the current player item and to be notified when the seek operation is complete.

The completion handler for any prior seek request that is still in process will be invoked immediately with the finished parameter

set to NO. If the new request completes without being interrupted by another seek request or by any other operation the specified

completion handler will be invoked with the finished parameter set to YES.

If you want to seeking more accurate, use the following method instead

player.seekToTime(<#T##time: CMTime##CMTime#>, toleranceBefore: <#T##CMTime#>, toleranceAfter: <#T##CMTime#>)

player.seekToTime(<#T##time: CMTime##CMTime#>, toleranceBefore: <#T##CMTime#>, toleranceAfter: <#T##CMTime#>, completionHandler: <#T##(Bool) -> Void#>)

this method will let the player seeking to specified time you asking,but will be slower(well..mostly depending on current media)

Apple's Doc

Use this method to seek to a specified time for the current player item.

The time seeked to will be within the range [time-toleranceBefore, time+toleranceAfter] and may differ from the specified time for efficiency.

Pass kCMTimeZero for both toleranceBefore and toleranceAfter to request sample accurate seeking which may incur additional decoding delay.

Messaging this method with beforeTolerance:kCMTimePositiveInfinity and afterTolerance:kCMTimePositiveInfinity is the same as messaging seekToTime: directly.

i've notice that current you are using

avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate))

you can try to use this method to seeking the specified time (slower of course)

avPlayer?.currentItem?.seekToTime(CMTimeMakeWithSeconds(secondo, frameRate), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)

Wish could help u out

Comments