如何理解 AVPlayerItem 及其与 AVPlayerItemVideoOutput 相关的当前时间

How to understand AVPlayerItem and it's Current Time in Relation to AVPlayerItemVideoOutput

我正在尝试使用 AVPlayerItem 和 AVPlayerItemVideoOutput 来抓取视频的帧图像。我看到的大多数示例都附加了一个 CADisplayLink 并简单地将显示时间 link 传递给 AVPlayerItemVideoOutput 上存在的 itemTime 函数,或者它们传递 CACurrentMediaTime() 而不是。

let itemTime = playerItemVideoOutput.itemTime(forHostTime: CACurrentMediaTime())

我的问题是我想抓取视频的特定一秒。在大多数功能中,如果您已经看到,您可以简单地构建一个时间并获得该帧。例如:

CMTime(seconds: 10.0, preferredTimescale: 600)//10 seconds

但是,这不是 AVPlayerItemVideoOutput 的工作方式。它似乎是从某个参考点计算它自己的时间(可能是在它被添加并在播放器上可用时)。我需要帮助了解通过特定帧获取视频所需的时间。

 //get item time so that I can grab a specific frame of the video
if playerItemVideoOutput.hasNewPixelBuffer(forItemTime: itemTime), 
   let pixelBuffer = playerItemVideoOutput.copyPixelBuffer(forItemTime: itemTime,itemTimeForDisplay: nil) ,
   case let i = CIImage(cvPixelBuffer: pixelBuffer){
 }

有些人可能会建议改用 AVAssetImageGenerator,这确实有效,但我已将 AVPlayerItemVideoOutput 的速度和效率限制为优于获取我需要的帧数。

您可以尝试调用 player.seek(to:),然后用 CACurrentMediaTime() 调用 copyPixelBuffer

但我不知道如果玩家从某个点开始播放,而您尝试从时间轴中的其他点获取像素缓冲区,您会取得多大成功。 我不认为 AVPlayerItemVideoOutput 是为了真正的“随机访问”。它可能(合理地)假设时间将以与其 AVPlayerItem.

相同的方式前进

然而,使用带有 AVAssetReaderTrackOutputAVAssetReader 可以让您通过设置 reader 的 timeRange 属性 来相对于资产的时间线进行搜索。