我明白的概念是 CMTime
以及它的作用。简而言之,我们有非常微小的一秒钟的分数,以浮点数的形式表示。当加起来的时候,它们会积累一个误差,随着解码回放的进行,这个误差会变得很大。例如,将100万次相加 0.000001
给我们 1.000000000007918
. 好吧,我知道了 CMTime
听起来是个好主意。
let d: Double = 0.000001
var n: Double = 0
for _ in 0 ..< 1_000_000 { n += d }
print(n)
// 1.000000000007918
然而,当试图转换一个随机的 Double
往返 CMTime
以上的错误与原来的区别相比就像一个笑话。Double
及其 CMTime
值。你可以猜测一下,在加入这些随机的 CMTime
值的一百万倍!
import CoreMedia
print("Simple number after 1,000,000 additions and diff between random ")
print("number before/after converting to CMTime:")
print("add:", String(format: "%.20f", 1.000000000007918))
for _ in 0 ..< 10 {
let seconds = Double.random(in: 0 ... 10)
// Let's go with the max timescale!
let time = CMTime(seconds: seconds, preferredTimescale: .max)
print("dif:", String(format: "%.20f", seconds - time.seconds))
}
// Simple number after 1,000,000 additions and diff between random
// number before/after converting to CMTime:
// add: 1.00000000000791811061
// dif: 0.00000000025481305954
// dif: 0.00000000027779378797
// dif: 0.00000000000071231909
// dif: 0.00000000024774449159
// dif: 0.00000000028195579205
// dif: 0.00000000029723601358
// dif: 0.00000000029402880131
// dif: 0.00000000044737191729
// dif: 0.00000000036750824606
// dif: 0.00000000043562398133
另一方面,是的,如果任何给定的 Double
可以准确地转换为 CMTime
,那么这就不是问题了。
问题。我想弄清楚,如果使用 "我的",是否合理?CMTime
单独用于时间交接(显然,除了无数的附加功能),还是说它只对那些以 CMTime
格式?为了说明一些情况,我有一个视频编辑应用程序,具有定制的UI(播放器,轨道,时间线),处理播放速度调整,轨道修剪和重新排列等。使用 Double
来表达时间值的效果很好,它干净、简单,而且能完成任务。但是 CMTime
感觉是 "正确 "的方式。然而,看到发生在一个 Double
转来转去,让我不禁感叹 CMTime
'的使用领域就像编码和解码媒体一样狭窄吗?
你的直觉是正确的。把螺丝刀当锤子用,可能大部分时间都能用,但这不是最好的用法。更重要的是,它可能遗漏了一些非明显的边缘情况,在这些情况下,它根本无法工作,或将导致更多的工作来锤入钉子(如双重加工)。
其次,你的转换方法是什么?也许你缺少一种边缘情况,比如不同的时间尺度。如果没有更多的信息,我真的无法给出进一步的指导。
CMTime在没有转换的情况下,用AVPlayer已经是帧数准确的了。这就是它的作用,不过要确保你把 toleranceBefore 和 toleranceAfter 设置为零。
注:我从事帧准确的videoaudio处理已经有十多年了。