在AVAsset中检测当前关键帧间隔 [英] Detect current Keyframe interval in AVAsset

查看:235
本文介绍了在AVAsset中检测当前关键帧间隔的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个可播放视频并允许用户在视频中前后滑动的应用程序.清理必须顺利进行,因此我们总是使用具有视频压缩属性AVVideoMaxKeyFrameIntervalKey:@1SDAVAssetExportSession重写视频,以便每个帧都将成为关键帧并允许平滑的反向清理.这样效果很好,并提供了流畅的播放.该应用程序使用来自各种来源的视频,并且可以录制在android或iOS设备上,甚至可以从网络上下载并添加到该应用程序中,因此我们最终得到了完全不同的编码,其中某些编码已经适合进行擦洗(每个帧)是关键帧).有没有一种方法可以检测视频文件的关键帧间隔,从而避免不必要的视频处理?我浏览过AVFoundation的许多文档,但没有找到一种明显的方式来获取此信息.感谢您对此的任何帮助.

I am working on an application that plays back video and allows the user to scrub forwards and backwards in the video. The scrubbing has to happen smoothly, so we always re-write the video with SDAVAssetExportSession with the video compression property AVVideoMaxKeyFrameIntervalKey:@1 so that each frame will be a keyframe and allow smooth reverse scrubbing. This works great and provides smooth playback. The application uses video from a variety of sources and can be recorded on android or iOS devices and even downloaded from the web and added to the application, so we end up with quite different encodings, some of which are already suited for scrubbing (each frame is a keyframe). Is there a way to detect the keyframe interval of a video file so I can avoid needless video processing? I have been through much of AVFoundation's docs and don't see an obvious way to get this information. Thanks for any help on this.

推荐答案

如果可以通过使用nil outputSettings创建AVAssetReaderTrackOutput来快速解析文件而不解码图像.您遇到的帧样本缓冲区有一个包含数组的附件数组,该字典包含有用的信息,包括该帧是否依赖于其他帧,或者其他帧是否依赖于该帧.我将前者解释为指示关键帧,尽管它给了我一些数字(一个文件中有4%关键帧?).无论如何,代码:

If you can quickly parse the file without decoding the images by creating an AVAssetReaderTrackOutput with nil outputSettings. The frame sample buffers you encounter have an attachment array containing a dictionary with useful information, include whether the frame depends on other frames, or whether other frames depend on it. I would interpret that former as indicating a keyframe, although it gives me some low number (4% keyframes in one file?). Anyway, the code:

let asset = AVAsset(url: inputUrl)
let reader = try! AVAssetReader(asset: asset)

let videoTrack = asset.tracks(withMediaType: AVMediaTypeVideo)[0]
let trackReaderOutput = AVAssetReaderTrackOutput(track: videoTrack, outputSettings: nil)

reader.add(trackReaderOutput)
reader.startReading()

var numFrames = 0
var keyFrames = 0

while true {
    if let sampleBuffer = trackReaderOutput.copyNextSampleBuffer() {
        // NB: not every sample buffer corresponds to a frame!
        if CMSampleBufferGetNumSamples(sampleBuffer) > 0 {
            numFrames += 1
            if let attachmentArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false) as? NSArray {
                let attachment = attachmentArray[0] as! NSDictionary
                // print("attach on frame \(frame): \(attachment)")
                if let depends = attachment[kCMSampleAttachmentKey_DependsOnOthers] as? NSNumber {
                    if !depends.boolValue {
                        keyFrames += 1
                    }
                }
            }
        }
    } else {
        break
    }
}

print("\(keyFrames) on \(numFrames)")

这仅适用于本地文件资产.

N.B. This only works for local file assets.

p.s.您不会说自己如何擦洗或玩耍. AVPlayerViewControllerAVPlayer?

p.s. you don't say how you're scrubbing or playing. An AVPlayerViewController and an AVPlayer?

这篇关于在AVAsset中检测当前关键帧间隔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆