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 ?
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 .
You could try a few things:
- lower the framerate of your video
- add more I-frames to your video (this may be slightly perverse, considering QA-1772's advice)
- decode (or better? encode) the video at a lower resolution
- lower the bitrate of the video
- measure how much faster than realtime
AVAssetReader
can decode at & replaceAVPlayer
with your ownMetal
+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.
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()
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.
来源:https://stackoverflow.com/questions/40506059/jerky-playback-from-avplayer-on-applying-rate-greater-than-2x