iOS AVPlayer 无法播放 240 fps 视频

Posted

技术标签:

【中文标题】iOS AVPlayer 无法播放 240 fps 视频【英文标题】:iOS AVPlayer cant play 240 fps video 【发布时间】:2017-11-27 15:19:41 【问题描述】:

我在更改 AVCaptureDeviceFormat 后录制了 240 fps 的视频。如果我将该视频保存在照片库中,就会出现慢动作效果。但是,如果我从文档目录播放该文件,使用 AVPlayer,我看不到慢动作效果。

播放视频的代码:

    AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:[AVAsset assetWithURL:[NSURL fileURLWithPath:fullPath]]];

     AVPlayer *feedVideoPlayer = [AVPlayer playerWithPlayerItem:playerItem];

    AVPlayerViewController *playerController = [[AVPlayerViewController alloc] init];

 playerController.view.frame = CGRectMake(0, 0, videoPreviewView.frame.size.width, videoPreviewView.frame.size.height);

 playerController.player = feedVideoPlayer;

【问题讨论】:

ios AVPlayer slow down的可能重复 【参考方案1】:

这有点烦人,但如果您不想降低质量,我相信您需要在 AVComposition 中重新创建视频。我很想知道是否有另一种方法,但这就是我想出的。从技术上讲,您可以通过 AVAssetExportSession 导出视频,但使用 PassThrough 质量将产生相同的视频文件,这不会是慢动作 - 您需要对其进行转码,这会降低质量(AFAIK。请参阅Issue playing slow-mo AVAsset in AVPlayer解决方案)。


您需要做的第一件事是获取源媒体的原始时间映射对象。你可以这样做:

let options = PHVideoRequestOptions()
options.version = PHVideoRequestOptionsVersion.current
options.deliveryMode = .highQualityFormat

PHImageManager().requestAVAsset(forVideo: phAsset, options: options, resultHandler:  (avAsset, mix, info) in

    guard let avAsset = avAsset else  return 

    let originalTimeMaps = avAsset.tracks(withMediaType: AVMediaTypeVideo)
        .first?
        .segments
        .flatMap  $0.timeMapping  ?? []


获得原始媒体(位于文档目录中的那个)的 timeMappings 后,您可以传入该媒体的 URL 和您想要重新创建的原始 CMTimeMapping 对象。然后创建一个可以在 AVPlayer 中播放的新 AVComposition。你需要一个类似于这样的类:

class CompositionMapper 

let url: URL
let timeMappings: [CMTimeMapping]

init(for url: URL, with timeMappings: [CMTimeMapping]) 
    self.url = url
    self.timeMappings = timeMappings


init(with asset: AVAsset, and timeMappings: [CMTimeMapping]) 
    guard let asset = asset as? AVURLAsset else 
        print("cannot get a base URL from this asset.")
        fatalError()
    

    self.timeMappings = timeMappings
    self.url = asset.url


func compose() -> AVComposition 
    let composition = AVMutableComposition(urlAssetInitializationOptions: [AVURLAssetPreferPreciseDurationAndTimingKey: true])

    let emptyTrack = composition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)
    let audioTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)

    let asset = AVAsset(url: url)
    guard let videoAssetTrack = asset.tracks(withMediaType: AVMediaTypeVideo).first else  return composition 

    var segments: [AVCompositionTrackSegment] = []
    for map in timeMappings 

        let segment = AVCompositionTrackSegment(url: url, trackID: kCMPersistentTrackID_Invalid, sourceTimeRange: map.source, targetTimeRange: map.target)
        segments.append(segment)
    

    emptyTrack.preferredTransform = videoAssetTrack.preferredTransform
    emptyTrack.segments = segments

    if let _ = asset.tracks(withMediaType: AVMediaTypeVideo).first 
        audioTrack.segments = segments
    

    return composition.copy() as! AVComposition

然后您可以使用CompositionMapper 类的compose() 函数为您提供一个准备在AVPlayer 中播放的AVComposition,它应该尊重您传入的CMTimeMapping 对象.

let compositionMapper = CompositionMapper(for: someAVAssetURL, with: originalTimeMaps)
let mappedComposition = compositionMapper.compose()

let playerItem = AVPlayerItem(asset: mappedComposition)
let player = AVPlayer(playerItem: playerItem)
playerItem.audioTimePitchAlgorithm = AVAudioTimePitchAlgorithmVarispeed

如果您需要将其转换为 Objective-C 的帮助,请告诉我,但它应该相对简单。

【讨论】:

以上是关于iOS AVPlayer 无法播放 240 fps 视频的主要内容,如果未能解决你的问题,请参考以下文章

iOS AVPlayer 变慢

AVPlayer 无法在 iOS 9 上播放

iOS 14.2 Beta - AVPlayer 无法播放 [关闭]

IOS AVPlayer 无法播放视频

AVPlayer 无法在 iOS8 上播放 NSDocuments 目录中的视频

iOS AVPlayer 在快退/快进后无法暂停