每个片段都少了一帧
你给四十个素材标好了入点和出点,发送到时间线上,剪辑看起来没问题。 几周后,有人核对时长时告诉你,每一个都比你标记的少了一帧。
一帧,看起来什么都不是,对交付规格来说却是天大的事。而且这个问题很 容易被带上线,因为它消失的地方,只是 API 里一个没人会看第二遍的词。
「出点」的两种理解方式
当你标记一个出点时,你想表达的是这两种意思之一,而且两种都合理:
- 包含(Inclusive) —— 出点所在的那一帧算作素材的 一部分。这是剪辑软件呈现给你看的方式。在 30fps 的素材上标 3 秒到 8 秒,你会预期得到 151 帧:五秒,加上你停下的那一帧。
- 不包含(Exclusive) —— 出点是素材停止的位置。 同样的标记会给出 150 帧。
两种理解都没错。麻烦出现在你的流程中一个环节按一种方式假设,下一个 环节按另一种方式假设的时候——因为差异正好是一帧,而一帧是看不见的。
那一帧到底去了哪里
Resolve 的脚本 API 在你把一个素材追加到时间线上时,接受的是起始帧和
结束帧。结束帧是不包含的:你得到的时长是
endFrame - startFrame。
所以,如果你把出点当作「包含」来保存——就像界面呈现给做标记的人那样 ——然后把这个数字原样交给 API,每一个素材到达时都会少一帧。不是第一个 会这样。也不只是那些棘手的会这样。是全部,悄无声息地,一直如此。
解决方法只需要一行:传入 outPoint + 1。难的部分
是知道自己需要这么做。
这里还有第二个值得知道的边界情况。如果范围坍缩到结束帧等于起始帧, 追加调用会返回 false,素材就根本不会到达。长度为零的范围,必须在 离开之前被限制为至少一帧。
为什么这个问题能在测试里活下来
范围离开一个素材应用时,不止走一扇门,而这些门彼此并不一致。时间线
API、EDL、媒体导出、ALE——在我经手过的系统里,这是四种各自独立的
转换,而且它们并不都遵循同一套约定。EDL 和 ALE 都把结束点当作不包含
处理。用 out - in 计算时长的导出也是不包含的。只有那个人
实际标记时用的界面是包含的。
这就是四次转换的机会,而只要有一处转换了两次,或者有一处压根没转换, 一帧就会跑偏。能让这件事保持可控的规则是:内部只保持一种约定,在每 一个出口精确地转换一次——绝不在中途转换。
怎么检查自己的结果
这个问题光靠肉眼是看不出来的。你得实际剪一段东西,数一数出来的结果。 标一个方便算术的范围——30fps 素材上的 3.0 秒到 8.0 秒——发送出去, 然后读时间线上的时长。包含算法给出 151 帧,不包含算法给出 150 帧。
数之前,先把时间线的帧率设成和素材一致。 这一步曾经 让我搭进去一整个下午。把 30fps 的素材放到 24fps 的时间线上,那 151 帧会变成 120 帧——多出来的那一帧连同其他几帧一起被取整抹掉了,检查 也就悄悄地不再是检查。入点还留在你放的位置,所以表面上看不出任何 问题。
还有两件事我会尽量避免。不要用秒来做算术:一个本该是 121 帧的值, 可能会先变成 5.041666…,再转换回帧数时被截断成 120。请用整数帧来 计算。也不要用那个返回素材源结束帧的 API 调用来验证——在我的测试里, 它的参照点在同一条时间线上的不同素材之间并不一致,所以没法用来判定 单帧级别的争议。改成读取偏移量和时长。
Divecut 是怎么做的
Divecut 内部把出点保存为「包含」,因为这才是做标记的人真正的意思,
并且只在每个出口转换一次。对 Resolve 交接来说,这意味着
endFrame = outPoint + 1,并且设有一帧的下限,这样即使
范围坍缩了,素材依然能到达。
我没有直接相信代码,而是按上面说的方法实际检查了一遍:30fps 素材上 3.0 秒到 8.0 秒的范围,在匹配的时间线上落地为 151 帧。这次测量正是 这篇文章存在的原因——我是在还没剪任何素材之前,把两条路径并排读了 一遍才发现这个不一致的,而这次计数正是确认修复有效的依据。
素材到达时依旧是 Log,原封不动,转换以时间线信息的形式应用,而不是 烧进画面里。不过那是另一篇文章的内容了。
Divecut 是一款面向 macOS 和 iPad 的素材浏览器。它用你拍摄时想要的色彩显示 Log 片段,让你用大白话就能搜索,再把你选中的片段以 Log 原样——连范围一起——交给 DaVinci Resolve。 查看全部功能。