我了解 CMTime
的概念及其用途。简而言之,我们用 float 表示非常小的一秒。添加后,它们会累积错误,随着解码/播放的进行,该错误会变得很严重。例如,将 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
之间的差异相比,上述错误看起来就像一个笑话code> 及其 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 来进行时间处理是否有意义(显然,除了一百万个添加项之外),或者它是否只对使用获取和返回值的 API 有用CMTime 格式?为了提供一些背景信息,我有一个带有定制 UI(播放器、轨道、时间线)的视频编辑应用程序,用于处理播放速度调整、轨道修剪和重新排列等。使用 Double
来表达时间值是可行的太棒了,它干净、简单并且能完成工作。但 CMTime 感觉是“正确”的做法。然而,看到 Double
在来回转换后会发生什么,让我想知道 CMTime
的使用领域是否与编码和解码媒体一样狭窄?
最佳答案
你的直觉是正确的。将 Screwdriver 用作锤子可能在大多数情况下都有效,但这不是最佳用途。更重要的是,它可能会遗漏一些不明显的边缘情况,在这些情况下它不起作用或会导致更多的工作需要敲定(例如双重处理)。
其次,你的转换方式是什么?也许您错过了一些边缘情况,例如不同的时间尺度。如果没有更多信息,我真的无法提供进一步的指导。
CMTime 对于 AVPlayer 来说已经是帧精确的,无需转换。这就是它的用途,但请确保将toleranceBefore 和toleranceAfter 设置为零。
注意:十多年来我一直致力于帧精确视频/音频处理。
关于swift - CMTime除了媒体编解码之外还有什么实际应用吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61449031/