Aegisub时间码格式详解

本文首发于我的Hexo博客:https://likianta.coding.me/2018/0213-224002/

注意:以下内容基于帧率为24FPS的视频讲解。

Aegisub时间码

如图所示是Aegisub的工作界面:

其中“开始/结束时间”是0:00:00.00的形式,小数点后有两位,代表的是多少毫秒,比如0:00:06.81就是6秒+810毫秒。

而本文中的另一个主角是“实际时间”,其形式为0:00:00.000,小数点后有三位,与前者的区别可不光是更加精确了,更重要的是同一时间下它们显示的时间值是不一样的,其换算关系为:

开始时间 = 实际时间 - 半帧的时间 再应用“去尾法”得到

举几个例子:

(注:24fps的视频,即 24帧 = 1s,换算得 1帧 = 1000/24ms,半帧 = 500/24ms ≈ 21ms)

实际时间对应的“开始时间”备注
0:00:06.8400:00:06.81840 - 21 = 819ms ≈ 0.81s
0:00:06.8810:00:06.86881 - 21 = 860ms ≈ 0.86s
0:00:09.0090:00:08.981009 - 21 = 988ms ≈ 0.98s
0:00:00.0000:00:00.00零秒处是特例

Aegisub每秒“溢出”

Aegisub的实际时间有一个特点,在24fps(每秒有0-23帧)的视频中,每秒的第0帧的毫秒数会递增“1ms”,如下表所示:

第几秒(总帧数)当前秒的第0帧的实际时间对应的“开始时间”备注
0 (0)0:00:00.0000:00:00.00零秒处是特例
1 (24)0:00:01.0010:00:00.981001 - 21 = 980ms ≈ 0.98s
2 (48)0:00:02.0020:00:01.981002 - 21 = 981ms ≈ 0.98s
3 (72)0:00:03.0030:00:02.981003 - 21 = 982ms ≈ 0.98s
4 (96)0:00:04.0040:00:03.981004 - 21 = 983ms ≈ 0.98s
5 (120)0:00:05.0050:00:04.981005 - 21 = 984ms ≈ 0.98s
6 (144)0:00:06.0060:00:05.981006 - 21 = 985ms ≈ 0.98s
30 (720)0:00:30.0300:00:30.0030 - 21 = 9ms ≈ 0.00s
60 (1440)0:01:00.0600:01:00.0360 - 21 = 39ms ≈ 0.03s

从上表可以发现一个规律,每增加一秒,其实际时间的第0帧的时间值会累加1ms,我们把这种现象叫做“溢出”,那么可以推算当溢出量累积到1000ms时(也就是在16分40秒的时候),那么会出现“加一秒”的情况(由于手头没有这么长的视频,所以暂时还没有实际验证过对不对)。

那么了解了这么一个规律,究竟有什么用呢?下面的实战是一个很好的例子:

实战:将Aegisub时间码转换为AE时间码

Aegisub的时间码格式为时:分:秒.毫米

Adobe After Effects(后面简称“AE”)的时间码格式为时:分:秒:帧

现在我们手上有一个从Aegisub保存下来的.ass文件,用记事本打开里面的内容为:

[Script Info]
; Script generated by Aegisub 3.2.2
; http://www.aegisub.org/
Title: 
Original Script: 
Original Translation: 
Original Editing: 
Original Timing: 
Original Script Checking: 
ScriptType: v4.00+
Timer: 100.0000
WrapStyle: 0
ScaledBorderAndShadow: Yes

[Aegisub Project Garbage]
Audio File: 开花火腿芝士面包 合成视频.mp4
Video File: 开花火腿芝士面包 合成视频.mp4
Video AR Mode: 4
Video AR Value: 1.777778
Video Zoom Percent: 0.500000
Active Line: 2
Video Position: 1440

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Default,Arial,20,&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2,2,2,10,10,10,1
Style: 封面白粗,Heiti SC,30,&H00FFFFFF,&H00FFFFFF,&H00FFFFFF,&H00FFFFFF,0,0,0,0,100,100,0,0,1,0,0,2,10,10,10,1
Style: 封面黑粗,Heiti SC,30,&H00000000,&H00000000,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,0.6,0,2,10,10,10,1
Style: 白色字体,Heiti SC,32,&H00000001,&H00FFFFFF,&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,0.4,0.5,2,10,10,6,1
Style: 水印,Heiti SC,16,&H00FFFFFF,&H00FFFFFF,&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,0.1,0.1,7,10,10,10,1
Style: 注释,Heiti SC,13,&H00FFFFFF,&H00FFFFFF,&H00FFFFFF,&H00000000,0,0,0,0,100,100,0,0,1,0.1,0.1,8,10,10,10,1

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
Dialogue: 0,0:00:04.69,0:00:06.23,白色字体,,0,0,0,,酵母
Dialogue: 0,0:00:06.23,0:00:08.36,白色字体,,0,0,0,,橄榄油
Comment: 0,0:01:00.03,0:01:00.08,白色字体,,0,0,0,,橄榄油
Dialogue: 0,0:00:08.36,0:00:10.07,白色字体,,0,0,0,,水
Dialogue: 0,0:00:10.07,0:00:12.32,白色字体,,0,0,0,,牛奶
Dialogue: 0,0:00:12.32,0:00:14.45,白色字体,,0,0,0,,糖
Dialogue: 0,0:00:17.45,0:00:19.20,白色字体,,0,0,0,,面粉
Dialogue: 0,0:00:19.20,0:00:20.91,白色字体,,0,0,0,,盐
Dialogue: 0,0:00:28.00,0:00:31.63,白色字体,,0,0,0,,发酵30分钟
Dialogue: 0,0:00:31.63,0:00:34.18,白色字体,,0,0,0,,巴西奶油奶酪
Dialogue: 0,0:00:34.18,0:00:37.39,白色字体,,0,0,0,,马苏里拉奶酪
Dialogue: 0,0:00:37.39,0:00:40.68,白色字体,,0,0,0,,火腿
Dialogue: 0,0:01:17.30,0:01:20.05,白色字体,,0,0,0,,蛋黄液
Dialogue: 0,0:01:25.60,0:01:27.90,白色字体,,0,0,0,,烘焙25分钟/180

假设我们通过某种方法删去了里面不重要的内容,并提取出来了每条字幕的“开始时间”、“结束时间”以及“文本内容”(依次如图中的红、黄、栏框注部分):

下面我们尝试着把开始时间转换成AE能够识别的时间码格式:

第一步:还原为实际时间

以第一条字幕为例,其开始时间为0:00:04.69,那么根据之前我们发现的规律,可求得其实际时间在0:00:04.7110:00:04.720之间。

第二步:利用AE表达式转换为AE时间码

我们取0:00:04.711作为计算结果(与实际时间的最大误差在9ms以内,是可以接受的),先将它换算为总秒数:

0:00:04.711 -> 4711(s)

然后利用AE表达式(以下为JavaScript代码):

var t = 4711;
var FPS = 24;
var timecode = timeToCurrentFormat(t, FPS); // 将总秒数根据当前视频帧率转换为AE时间码格式
return timecode; // 得到`0:00:04:17`,即表示第四秒第17帧处

这样子就转换完成了……其实并没有。

通过在测试中观察实际画面发现,Aegisub的帧数和AE的帧数总是相差一帧,因此我们还要再减去一帧才是AE真正的时间码:

第三步:改进(减一帧)

var timecode_aegisub = `0:00:04.69`;
var frame_duration = 0.042;
var half_frame_duration = 0.021;

var t = 4690 + half_frame_duration - frame_duration;
var FPS = 24;
var timecode_ae = timeToCurrentFormat(t, FPS); // 将总秒数根据当前视频帧率转换为AE时间码格式
return timecode_ae; // 得到`0:00:04:16`,即表示第四秒第16帧处

相关阅读

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值