Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you get smooth high-rate playback from AVPlayer?

AVPlayer has a property called rate that is meant to control the playback rate. 1.0 is normal speed while values like 2.0 or 5.0 should playback at 2x and 5x respectively.

Whenever I set a playback rate value higher than 1.0 (say 10.0), the playback is very choppy and it looks like a large number of frames are getting dropped as the player can't keep up.

However, the same values in QuickTime Player (with the same movie), produce smooth playback for rates of 2x, 5x, 10x, 30x and 60x (as reported by the QuickTime Player).

I created a test OS X application that contains nothing more than an AVPlayerView and two buttons for setting the playback rate. A rate of 1.0 works as expected, but a rate of 10.0 produces very choppy playback.

However, the AVPlayerView has an odd quirk in that if you mouse-click on the playback timeline to seek to another location (while it's playing at 10x and choppy), then the AVPlayerView will "fix" the playback and the movie will be played smoothly at 10x. All it took was clicking on the playback timeline.

Does anyone know how to get smooth playback for rates other than 1x? It's obviously not a hardware problem or a file size problem because both QuickTime Player and AVPlayerView can do it.

Attempts

This question suggests that it might be an audio issue (and indeed both QuickTime Player and AVPlayerView mute the audio when forwarding) but all attempts on my part to either disable all audio tracks, mute all tracks or change the audio pitch algorithm did not seem to make a difference. Playback was still choppy even when there was no audio present.

I've also tried stopping playback and then calling prerollAtRate:completionHandler with the new rate but that doesn't make a difference either.

What is it that QuickTime Player and AVPlayerView are doing that allows for smooth movie playback at rates of 10x, 30x or even 60x?

like image 757
kennyc Avatar asked May 20 '15 10:05

kennyc


1 Answers

This is only a workaround.

When the playback rate is changed from 0.0 to a large value, if this is the first zero-to-nonzero transition in playback rate since the last call to AVPlayer.replaceCurrentItem, playback is smooth (and audio is automatically muted). It is necessary that this is the first such transition: merely setting the rate to 0.0 first and then to the desired rate does not work.

So, for example, this will produce smooth playback at high speeds:

func setPlayerRate(player: AVPlayer, rate: Float) {
    // AVFoundation wants us to do most things on the main queue.
    DispatchQueue.main.async {
        if (rate == player.rate) {
            return
        }
        if (rate > 2.0 || rate < -2.0) {
            let playerItem = player.currentItem
            player.replaceCurrentItem(with: nil)
            player.replaceCurrentItem(with: playerItem)
            player.rate = rate
        } else {
            // No problems "out of the box" with rates in the range [-2.0,2.0].
            player.rate = rate
        }
    }
}
like image 118
Jamborino Avatar answered Nov 11 '22 11:11

Jamborino