Jerky playback from avplayer on Applying Rate greater than 2x
Asked Answered
P

5

5

I want to tweak Avplayer rate , I able to do with help of

[_avplayer play];
[_avplayer setRate:1.5];

Also disabled audio tracks , it is running good when it is less than 2.0. But when we apply it greater than 2X it results in Choppy or jerky video.

When i googled about this - I found this one link suggesting same behaviour

https://developer.apple.com/library/content/qa/qa1772/_index.html

Playing at rates greater than 2.0 can result in jerky or choppy playback when the data rate or other processing requirements of playing at the specified rate exceeds the ability of AVFoundation to keep up. In those cases, AVPlayer automatically degrades the quality of playback in order to keep up, employing a tier of fallback strategies depending on prevailing conditions. One tier of degradation is to decode and display only I-frames within the video substream, and this can indeed appear to be choppy.

Can any one help like if it so , than what approach shall i use to achieve same ?

Permatron answered 9/11, 2016 at 11:35 Comment(0)
P
11

As @Rhythmic suggested these ways can be implemented but these all are kind of hassle . I googled it more and found a way and it is working very fine no jerk or choppy .

Just do not set rate , set Rate like this . First create instance of AVPlayer , AVPlayerItem and AVAsset .

  AVMutableComposition *composition = [AVMutableComposition composition];
        NSError *error = nil;
        [composition insertTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
                             ofAsset:asset
                              atTime:kCMTimeZero error:&error];
        [composition scaleTimeRange:CMTimeRangeMake(kCMTimeZero, asset.duration)
                         toDuration:CMTimeMultiplyByFloat64(asset.duration, 1 / rate)];
        AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:composition];
        self.avRefPlayer = [AVPlayer playerWithPlayerItem:playerItem];

        self.avRefPlayerLayer = [AVPlayerLayer layer];

        [self.avRefPlayerLayer setPlayer:self.avRefPlayer];
        [self.avRefPlayerLayer setFrame:_refrencedView.bounds];
        [self.avRefPlayerLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

this code can even support more than 2x or 4x speed easily .

Permatron answered 15/11, 2016 at 6:17 Comment(2)
FWIW, two applications that I created—one in Objective-C and the other in Swift—both exhibit this problem. It's worth noting that the issue is not the media file: Quicktime Player, for example, has no trouble playing it back very fast, whereas my applications cannot seem to do more than about 1.5x. I've just implemented the above in Swift and found that it does work. I can play back at, for example, 9x, no problem.Gunpowder
This works great. However event by adjusting time scale changes and doing the proper seeks, changing the speed while playing the video is still very hard get right without weird frame jumps. Since the framework is obviously capable of playing at fast rates, I still don't understand while the rate property doesn't support it...Railey
S
4

Thanks to Kshitij Godara.

Converted to Swift 4.

let timeRange = CMTimeRangeMake(kCMTimeZero, CMTime(seconds: videoDuration, preferredTimescale: 1))
let composition = AVMutableComposition()
try composition.insertTimeRange(timeRange,
                               of: asset,
                               at: kCMTimeZero)
composition.scaleTimeRange(timeRange, toDuration: CMTimeMultiplyByFloat64(asset.duration, Float64(1.0 / rate)))
let playerItem = AVPlayerItem(asset: composition)
let player = AVPlayer(playerItem: playerItem)
player.play()
Smithereens answered 31/7, 2018 at 22:1 Comment(0)
S
1

You could try a few things:

  1. lower the framerate of your video
  2. add more I-frames to your video (this may be slightly perverse, considering QA-1772's advice)
  3. decode (or better? encode) the video at a lower resolution
  4. lower the bitrate of the video
  5. measure how much faster than realtime AVAssetReader can decode at & replace AVPlayer with your own Metal + AVAssetReader path if you think that some performance has gotten lost in transit. Don't forget to consider audio, too, if you take this path.
Slapup answered 10/11, 2016 at 0:46 Comment(0)
G
0

This seems to be a bug in AVFoundation. It can play smoothly at fast rates for many videos where, under most circumstances, it doesn't. For example, one can use AVPlayerView's floating controller style to expose a fast-forward button. Clicking this button repeatedly results in smooth, fast playback where simply setting AVPlayer.rate does not.

In my answer to this question I explain a workaround for this problem.

Gunpowder answered 17/2, 2017 at 12:1 Comment(0)
V
0

If you want to switch 0~4 rate, you can initialize an AVMutableComposition that has been scale duration to 1/2, and then set the rate to 0~2 during playback.

Vespiary answered 22/12, 2021 at 5:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.