本文首发于我的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.840 0:00:06.81 840 - 21 = 819ms ≈ 0.81s
0:00:06.881 0:00:06.86 881 - 21 = 860ms ≈ 0.86s
0:00:09.009 0:00:08.98 1009 - 21 = 988ms ≈ 0.98s
0:00:00.000 0:00:00.00 零秒处是特例

Aegisub每秒“溢出”

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

第几秒(总帧数) 当前秒的第0帧的实际时间 对应的“开始时间” 备注
0 (0) 0:00:00.000 0:00:00.00 零秒处是特例
1 (24) 0:00:01.001 0:00:00.98 1001 - 21 = 980ms ≈ 0.98s
2 (48) 0:00:02.002 0:00:01.98 1002 - 21 = 981ms ≈ 0.98s
3 (72) 0:00:03.003 0:00:02.98 1003 - 21 = 982ms ≈ 0.98s
4 (96) 0:00:04.004 0:00:03.98 1004 - 21 = 983ms ≈ 0.98s
5 (120) 0:00:05.005 0:00:04.98 1005 - 21 = 984ms ≈ 0.98s
6 (144) 0:00:06.006 0:00:05.98 1006 - 21 = 985ms ≈ 0.98s
30 (720) 0:00:30.030 0:00:30.00 30 - 21 = 9ms ≈ 0.00s
60 (1440) 0:01:00.060 0:01:00.03 60 - 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帧处

相关阅读

Aegisub时间码格式详解相关推荐

  1. Java字节码(.class文件)格式详解(一)

    原文链接:http://www.blogjava.net/DLevin/archive/2011/09/05/358033.html 小介:去年在读<深入解析JVM>的时候写的,记得当时还 ...

  2. 三维重建:PNG格式详解-与LibPNG使用

    PNG图像包含了骨骼信息,左边的图像比右边的大几十K,包含了骨骼信息:        PNG格式详解:https://blog.mythsman.com/post/5d2d62b4a2005d7404 ...

  3. Android 源码编译详解【合集篇】

    Android 源码编译详解[一]:服务器硬件配置及机型推荐 做 Android系统开发多年,开发环境都是入职就搭建好了,入职时拿个账号密码就直接开始搞开发了,年初换了新公司,所有的项目都是刚起步,一 ...

  4. PE 格式详解与试验

    PE 格式详解与试验 可执行文件结构分析 DOS头 文件头 可选头 PE RVA 地址与文件地址转换 块表 Section Header 导入表 Data Directory 基址重定位 reloc ...

  5. 使用Gin框架集成JWT,源码、详解、面试问题

    使用Gin框架集成JWT,源码.详解.面试问题 一.什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519). ...

  6. Ffmpeg快速命令使用 Ffmpeg选项详解 Ffmepg格式详解 常见视频文件格式详解

    http://www.ffmpeg.com.cn/index.php/%E9%A6%96%E9%A1%B5 Ffmpeg快速命令使用 From Ffmpeg工程组 Jump to: navigatio ...

  7. AAC音频格式详解和实战解析

    AAC音频格式详解和实战解析 一.基本概念 AAC:即MPEG-2 Advanced Audio Coding,分为流格式和文件格式.文件格式主要用于文件存储和文件播放,流格式主要用于流媒体在线播放. ...

  8. http状态码查询,各种返回码的详解(200、206、500、416、403、404)

    http状态码查询,各种返回码的详解(200.206.500.416.403.404) 文章由帮客之家于2013-11-25 12:11:44分享 评论(324) HTTP状态码,我都是现查现用. 我 ...

  9. php serialize取值,PHP 序列化(serialize)格式详解

    PHP 序列化(serialize)格式详解(转) 1.前言 PHP (从 PHP 3.05 开始)为保存对象提供了一组序列化和反序列化的函数:serialize.unserialize.不过在 PH ...

最新文章

  1. 做301定向跳转对网站优化有什么帮助?
  2. python官网如何调中文-django的settings中设置中文支持的实现
  3. 8.2.1.3 Range 优化
  4. javascript:闭包的总结
  5. pigeon hole
  6. 浅谈 EF CORE 迁移和实例化的几种方式
  7. app账号退不出去_最新!多交的税可以退,同学,你今天退税了吗?
  8. 帝国cms数据库php调用tag,帝国CMS列表内容模板调用TAG的两种方法
  9. 链表的实现 -- 数据结构与算法的javascript描述 第六章
  10. 一个好用的在线画图工具
  11. DDos攻击防御策略
  12. win10 安装 framework7 报错解决思路和方法
  13. Java操作xls文件,数据去重
  14. Linux 网络排障工具 MTR --鸟枪换炮事半功倍
  15. 现代计算机发展经历的阶段,计算机的发展经历了那几个阶段
  16. AndroidManifest文件
  17. 把团长的身姿藏在代码里
  18. 邮件撤回成功后对方还能看到吗?163邮箱能群发邮件吗?
  19. 利元转债,奕瑞转债上市价格预测
  20. ABCD选项的排序方式

热门文章

  1. 【高烧39°考研上岸】23上交819考研经验分享
  2. 基于有Vue基础的微信小程序开发学习笔记
  3. SQL多表数据的查询汇总
  4. 在oracle环境变量里,oracle环境变量详解
  5. 高通最新处理器指定三星为唯一制造商
  6. 7-164 统计字符个数
  7. 自动阅读专业版---原薅羊毛专业版
  8. python如何安装pdfminer_python2/3安装PDFMiner.six将PDF转HTML/TXT - pytorch中文网
  9. c语言 until,for,while,until
  10. 城池 方格 三国 java_为什么三国演义中攻打城池非要一个一个来?终于找到答案啦...