TA的每日心情 | 无聊 2023-3-18 18:33 |
---|
签到天数: 3 天 [LV.2]偶尔看看I
星辰大海
- 积分
- 406747
|
本帖最后由 Lambholl 于 2022-11-17 13:49 编辑
首先,众所周知的一件事情是:ASS字幕的计时精度是 0.01 秒:
而我们平时所看的视频(动画和电影)是 24000/1001 ≈ 23.976 帧,一帧持续约 41.71 ms,即 0.042 秒,那么这个精度完全足够;
就算碰上 60 帧的视频,一帧也会持续 0.0167 秒,也应当是足够的;当然碰上 120 帧的视频的屏幕字,那就另当别论了。
这个精度在做对话字幕和屏幕字的时候当然是够用的,但是当碰上字幕特效呢?
前段时间我做了一个字幕连续旋转的特效:
如图所示,在两行字幕之间通过连续的旋转平滑过渡:
我先对字幕进行逐列clip,然后使用了retime来实现连续变化:
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function getDeltaTime(delx) local result=300*(math.log(delx+500)-math.log(10000000))+2980+800 return result end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,xNum1 = 0
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function aaa(x0) xNum1 = x0 return '' end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function aab() xNum1 = xNum1+1 return '' end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,template char notext,!aaa($sleft)!
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,template char,!maxloop($swidth)!!aab()!!retime("line",-1060+getDeltaTime(xNum1),-1050+getDeltaTime(xNum1))!{\blur2\pos($sx,!$sy+25!)\an4\frx90\t(0,140,0.5,\frx0)\t(!$ldur-130!,!$ldur-10!,2,\frx-90)\clip(!xNum1!,0,!xNum1+1!,1080)}
复制代码 先使用了对数函数进行计算,以达到离边界近的列之间开始旋转时间差较大、离边界较远的列开始旋转的时间差较小的效果,然后对每列进行 clip,使用 retime 做到列与列之间的连续变化;
但是可以看见,字幕出现了被「割裂」的情况,即因为计时精度只有 0.01 秒,因此字幕被分成了一个个小块,每个小块中的每个列在同一时刻旋转的角度相同,而不同块之间同一时刻的角度差则肉眼可见,这显然是写特效的时候不希望出现的。
那么,有解决方法吗?
于是我对代码进行了一些修改:
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function getDeltaTime(delx) local result=300*(math.log(delx+500)-math.log(10000000))+2980+800 return result end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,xNum1 = 0
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function aaa(x0) xNum1 = x0 return '' end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,code,function aab() xNum1 = xNum1+1 return '' end
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,template char notext,!aaa($sleft-5)!
- Comment: 0,0:00:00.00,0:00:00.00,ED-EN,,0,0,0,template char,!maxloop($swidth+10)!!aab()!!retime("line",-1060,-1060+getDeltaTime($lright))!{\blur2\pos(!$sx+($swidth/2)!,!$sy+25!)\an5\frx90\t(!getDeltaTime(xNum1)!,!getDeltaTime(xNum1)+140!,0.5,\frx0)\t(!$ldur-140+getDeltaTime(xNum1)!,!getDeltaTime(xNum1)+$ldur!,2,\frx-90)\clip(!xNum1!,0,!xNum1+1!,1080)}
复制代码 结果如图:
因此,事实证明,ASS 字幕的计时精度其实能精确到 0.001 秒,只需要 \t 即可做到;
但是在播放的时候,我也发现了一个问题:修改后的字幕只能使用 libass 才能流畅渲染(XySubFilter with libass 及 AegisubDC 中的 libass),而修改前的字幕则可以使用其他滤镜流畅渲染;而实际观感上,其实观众看不出区别,因此这是一点需要取舍的。
字幕文件:
RWBY_ED.7z
(1.83 MB, 下载次数: 16)
杂谈
libass 的作者正在准备开发 ASSv5,对此我个人有一些设想,不过要写成英文实在是有点难,不知道哪位路过的大佬能不能帮忙写成英文提交个issue:
我个人认为可以加入的
1. 更改字号对齐方式,不再以高度作为字号的标准,而是以宽度;
2. 允许自定义基线偏移;
3. 引入标点挤压;
4. 允许将计时精度精确到1ms(毕竟此文所述方法还是有些麻烦);
5. 中西文/数字混排时,自动在中间加入 1/4 全角字面框宽度的间隔;
6*. 引入一种新的clip方式,不是在整个屏幕中clip,而是对一行字幕的文本clip(方便做出文字碎片效果)
关于第一点的说明,引用:
需要特别注意 在ASS字幕渲染字体的引擎中 1.3x版本的 方正蘭亭黑_BIG5 系列和1.20版本 (VCB-S字体包中版本) 在相同字号下显示的字形大小存在差异 (实际测试,在Word等工具中并不会出现这种情况;坐等大佬解答)
根据@tmdtmdtmdqq 的推测,其原因应该为
「感觉word那种是用版面间距算的字号,每个同号数的字体间距是等宽的(看扫黑的区域,每行都是等宽的)
aegisub那个字号,感觉像用字体内某个参数算的字号,不同字体宽度不一样」
关于第三点的说明,可以看 oooooohmygosh老师的视频(事实上 Word 里面会自动这么调整)
然后最后,还是打个广告:字幕组急招翻校
要不是为了打广告才不写这帖呢
|
|