AVAsset 视频调整时长

AVAsset video adjust duration

鉴于已从资产中读入的 CMSampleBuffers 列表,我想调整资产的持续时间,使其长度为原始资产的一半(速度的两倍)。

目前我生成新时间戳的函数如下所示:

func adjustTimeStampsForBuffers(buffers: [CMSampleBuffer]) -> [CMTime] {
    let frameCount = buffers.count
    // self.duration is CMTimeGetSeconds(asset.duration)
    let increment = Float(self.duration / 2) / Float(frameCount)
    return Array(0.stride(to: frameCount, by: 1)).enumerate().map {
        let seconds: Float64 = Float64(increment) * Float64([=10=].index)
        return CMTimeMakeWithSeconds(seconds, self.asset.duration.timescale)
    }
}

但这似乎不起作用,输出的资产实际上是长度的两倍,而不是一半。谁能指出我哪里出错了?

编辑:

感谢@sschale,这是我的最终答案:

func adjustTimeStampsForBuffers(buffers: [CMSampleBuffer]) -> [CMTime] {
    return buffers.map {
        let time = CMSampleBufferGetPresentationTimeStamp([=11=])
        return CMTimeMake(time.value, time.timescale * 2)
    }
}

不是计算新值,而是调整时间戳。

根据我对 docs 的阅读,看来 self.asset.duration.timescale 可能是这里的关键,因为更改它会影响整个文件(如果我理解您的参考资料)重新使该时间刻度适用于整个文件,或者您可能需要在每个缓冲区中调整它)。

有关详细信息,请参阅 here

相关栏目:

A CMTime is represented as a rational number, with a numerator (an int64_t value), and a denominator (an int32_t timescale). Conceptually, the timescale specifies the fraction of a second each unit in the numerator occupies. Thus if the timescale is 4, each unit represents a quarter of a second; if the timescale is 10, each unit represents a tenth of a second, and so on. In addition to a simple time value, a CMTime can represent non-numeric values: +infinity, -infinity, and indefinite. Using a flag CMTime indicates whether the time been rounded at some point.

CMTimes contain an epoch number, which is usually set to 0, but can be used to distinguish unrelated timelines: for example, it could be incremented each time through a presentation loop, to differentiate between time N in loop 0 from time N in loop 1