[魔典] 日本动画字幕制作 #04 绘词曲之婉转
引导语

字幕是仅视觉的,但也总是能从某些角度做到与音乐、与意境共语的。

此后将会抛开“是否改如此大程度地影响原片”或“做这么多值得吗”等问题,也将可能会难以上手。

K轴

先还是来点简单的,为歌词打K轴

准备:
1. 在打歌词的轴时开始时间和结束时间通常会非常敏感,也可能需要根据具体效果作调整
2. 视频区域关掉,或者拉到最小
3. 水平缩放拉满
4. 至少有日语基础
5. 设置,音频中,将“标记拖动开始灵敏度”调高至5左右
6. 打开卡拉OK模式
7. 准备好受折磨

图示的水平缩放仅为1/2

拉满后还是可以大致辩清的

一般有两种打K轴的方式,一是按词隔开,二是逐字。后者的折磨程度肯定更上一层楼,并且可能处理中文时会更折磨

完成后形式即为:【{\k41}色{\k45}違{\k25}い{\k20}の{\k42}君{\k23}の{\k23}オ{\k17}ッ{\k22}ド{\k24}ア{\k25}イ{\k38}ズ】

好了,你已经会打K轴了,快去试试吧!(

大致步骤与打轴基本一致,听前几百毫秒后几百毫秒找到边界,但需要精细非常多
左键点击区域后即调整该区域,鼠标拖动虚线以修改时间
完事后记得按确定保存!

直接逐字打{\k}啥的也不是不行(

如果歌词不准备打轴的话,那中文翻译的长短或者对应关系也就挺无所谓的了
但如果要打轴,中文翻译基本会在打完轴后改若干细节,比如为了对应节奏或者限制字数等

这部分基本无压力(
不过确实对比后面需要的工作,还真的可能没什么压力

卡拉OK

如04结语所说——珍惜生命!请酌情跳过此部分
如果要参考,其中部分词或许初次看并不能理解是什么意思,此类或在后文解释

创建一个和要处理的歌词同样式的行,打上注释,在特效行输入template
内容输入{\blur4},主菜单中点击自动化,点击应用卡拉OK模板
即可生成如下图形式的fx行

原本打好K轴的四行被注释掉,并且特效栏改为了【karaoke】,而后生成的行的特效栏均为【fx】且按K轴分隔开了(但没有按K轴的时间而是直接原轴时间),所有行都加上了【{\blur4}】,但还有些行的{\blur4}后没有文字

但大致的变化即如此,模板行不会进行任何改变,原K轴歌词行变成了karaoke行,生成了fx特效行

karaoke行在修改完后一般不会需要改变,特效行是生成的,那么重点自然而然就是模板行

另,在执行模板后,会删除原有的所有fx行,生成新的fx行

声明

也就是上面的template这个词

声明有template和code两种,template为决定了fx行具体形式,而code一般为template提供lua支持

模板行开头必须声明是template或是code
template默认修饰语为syl
code默认修饰语为once

修饰语

code once

once仅作用于code行

先于其他行执行,同为once行则顺序执行,只执行一次

通常用于声明常量,或者声明函数等
如:【sakura = "m 0 0 l -10 -24 b -30 -22 -38 -2 -37 27 b -33 57 -18 75 0 86 b 18 75 33 57 37 27 b 38 -2 30 -22 10 -24 l 0 0 "】或【function isOdd(x) local r=x%2 if(r==0) then return 0 else return 1 end end】
前者声明一个【sakura】为一个字符串,当然字符串的内容就是绘图,便于后续template行使用
后者声明一个【isOdd】函数,后续code或者template需要判断奇偶数时即可用isOdd()返回0或1

code line

line可作用于code行及template行
line仅在作用于template行时可以命名

每行执行一次

通常用于为部分行单独设置特效组
如:【fxgroup.A = (line.actor == "fx-LRC-OP-A")】
命名一个特效组A,且如果该行的actor(说话人)为fx-LRC-OP-A时,A组即为该行
而后如【template line fxgroup A】即可专门为该行设置特效

code syl

syl可作用于code行及template行

每个音节执行一次
如【{\k233}总共{\k233}执行三次】会执行三次,一次是blank,一次是对“总共”,一次是对“执行三次”

通常用于为部分音节设置特效组
如:【fxgroup.A = (syl.inline_fx ~= "EFF")】
命名一个特效组A,且如果该音节有【\-EFF】内联特效时,A组即为该音节
而后如【template syl fxgroup A】即可专门为该行设置特效

code all

all可作用于code行及template行
all可添加在once、line、syl后,如【code syl all】

将该行作用于所有样式

默认情况下code和templ都仅作用于同样样式的行,但加上all标签后就没有此界限

template line <名称>

line可作用于code行及template行
line仅在作用于template行时可以命名,<名称>可有可无

按行生成特效行

一般的,即为每行生成一些特效行
此时如果karaoke行有K轴音节,则每个音节都会运行一次但只会生成一行

但template line也可以逐字或每几个字做特效

template pre-line <名称>

pre-line仅可作用于template行

为对应名称的template line生成一些需要的结构,并拼接在对应的template line生成的特效行的内容前

如果不加名称,相当于单独为每行生成一行不带内容的

加了名称后,仅作用于同名称的template line行
如:特效栏为【template pre-line eff】内容为【{\blur4}】,且有其它行特效栏为【template line eff】内容为【{\bord2}】时,后者按理应该生成的【{\bord2}内容】将改为【{\blur4}{\bord2}内容】,template pre-line eff行生成的内容将拼接在template line eff行生成的内容前

template syl

syl可作用于code行及template行

每个音节生成一些特效行
如【{\k233}总共{\k233}生成三轮】会执行三轮,一轮是blank,一轮是对“总共”,一轮是对“执行三次”

打K轴后常用,一般需配合retime使用

template syl char

char仅在template syl时有意义

逐字生成一些特效行
如【{\k233}总共{\k233}生成七轮】会执行六轮,分别对这六个字

一来可用于并非逐字K轴的歌词做逐字的特效

二来用于未K轴的歌词做逐字的特效
但此时仍需要karaoke行开头有{\k233}

template syl multi

multi仅在template syl时有意义

为每个高亮执行一次

如【{\k10}鏡{\k10}#{\k10}#{\k30}の{\k15}中{\15}#{\k30}の】其中【鏡】为【かがみ】三个音,【中】为【なか】两个音
此时{\k10}鏡{\k10}#{\k10}#会使鏡的总时长仍为30,但额外高亮两次,也就可以于此再做两轮特效以使其有视觉表现

template furi

为假名标注按syl执行

目的类似于multi,为了让日语这样一个字可能由多个音组成的能够根据发音数增加视觉表现(或者整活)

如【{\k10}鏡|<か{\k10}#|<が{\k10}#|<み{\k30}の{\k15}中|<な{\k15}#|<か{\k30}の】,使用【|<】以进行假名标注,多音同multi一样使用【#】占位

特别的,template syl furi是唯一例外的有效组合
抛开效果不谈,能够统一生成一个特效

all

all可作用于code行及template行

将该行作用于所有样式

默认情况下code和templ都仅作用于同样样式的行,但加上all标签后就没有此界限

noblank

noblank仅作用于template行

一般用于template syl,使其不再对blank生成特效行

本身为空、\k0、空格都可能会在template syl时生成空行
基本template syl无脑加这个修饰语就行,减少无效行

notext

notext仅作用于template行

一般template line、template syl等都会在其后跟上内容(前两例分别会跟行内容、音节内容)
使用notext可以使输出去掉这部分内容

如一些行用于为每行/每音节/每字增加额外的特效,加上notext后会非常有效

keeptags

keeptags仅作用于template行

一般template line、template syl等都会在其后跟上内容(前两例分别会跟行内容、音节内容),但内容不会涵盖所有{}内的特效标签
如【{\bord2\blur4}文字内容】一般情况下视为内容的只有“文字内容”四个字
使用keeptags可以使输出增加上原特效标签

另有不常用的notags

在char、multi下不生效

loop <次数>

使该行重复运行几次
与maxloop等价,但loop后的次数仅能为一般正整数,不能是计算式或变量

会为该行生成一个变量【j】,其即为第几次运行

loop修饰语与repeat修饰语等价

fx <特效名>

仅作用于template行

使该行作用于指定特效名

特效名为内联特效的名称
如【{\k10\-EFFA}鏡|<か{\k10}#|<が{\k10}#|<み{\k30\-DE}の{\k15\-EFFB}中|<な{\k15}#|<か{\k30\-DE}の】
【\-EFFA】设定了一个EFFA内联特效名,且作用直下一个结束或下一个内联特效前
【\-DE】设定了一个DE内联特效名,此处将其当为前一个内联特效的结束语
【\-EFFB】再次设定了一个新的内联特效名

fxgroup <特效组名>

仅作用于template行

使该行作用于指定特效组

特效组名一般在code行中声明

一般的,code line中【fxgroup.A = (line.actor == "fx-LRC-OP-A")】然后template line fxgroup fx-LRC-OP-A中写入特效
则会使这部分特效作用于说话人设为fx-LRC-OP-A的行

另,code syl中【fxgroup.A = (syl.inline_fx ~= "EFF")】然后template syl fxgroup EFF中写入特效
则会是这部分特效作用于未被标记为EFF内联特效的音节
而template syl fx EFF可以再对标记为EFF内联特效的音节做处理

内联特效

仅适用于code syl和template syl fx/fxgroup组合,且需打过K轴的

在karaoke行中使用【{\-<特效名>}】,其中<特效名>自行设定(但不要设为可能的关键词),使后续内容的内联标签改为此特效名
默认开始的内联特效为空(""),此后例如用\-EFF后内联特效改为EFF("EFF"),此后不可再设为空,但可再另行指定一个标签如\-DE,不用DE这个特效即可

在code syl中使用syl.inline_fx获得当前音节的内联特效
如【{\k10}空{\k10\-EFFA}效果A{\k10\-EFFB}效果B】
第一个音节blank,内联特效为""
第二个音节"空",内联特效为""
第三个音节"效果A",内联特效为"EFFA"
第四个音节"效果B",内联特效为"EFFB"

template syl后跟fx EFFA即可将其作用于上述下的"效果A"这个音节

而如果code syl中另设特效组fxgroup,命名为DEF,将除EFFA外所有音节包括在内——【fxgroup.DEF = (syl.inline_fx ~= "EFFA")】
然后使用template syl fxgroup DEF即可将其作用于除EFFA外所有音节

内联变量

内联变量均以$开始,仅在template行有效

与坐标有关的内联变量均会取整,所以在实现部分精细的特效时可能会影响效果

根据对象不同,内联变量的含义可能也会改变
如对于template line的$dur为整行持续时间,而对于template syl则是该音节持续时间
但也可仔细地分别使用$ldur和$sdur以便于区分

自适应变量

在以line为对象时,矩形区域为整行文字的上下左右边界所组成的区域
在以syl为对象时,矩形区域为该音节的上下左右边界所组成的区域

$top$bottom$left$right分别为上、下、左、右四个边缘的坐标值
$center为中央的横坐标,$middle为中央的纵坐标
$width相当于$right-$left,$height相当于$bottom-$top

$dur为line/syl的持续时间
$kdur为$dur/10,相当于以\k后的值为单位,不过$dur足够了

$start$end为line/syl的开始、结束时间
$mid相当于($start+$end)/2,中点时间,不过$start和$end足够了

$i为line的行数或syl的音节数

另有$x和$y分别指line/syl在默认\an对齐方式下的横、纵坐标

当然,介绍此处并非是需要使用,而是便于理解
因为以上变量无一例外如果改为$l开头则以line为对象,改为$s则以syl为对象
精确地指定无论如何都是更好的

template line

参考自适应变量,在line下会有:
$ltop  $lbottom  $lleft  $lright  $lcenter  $lmiddle  $lwidth  $lheight  $ldur  $lstart  $lend  等

仅line内联变量

$layer为该行设定的层数

$style为该行的样式名称

$actor为该行的说话人

$margin_l、$margin_r、$margin_v分别为该行的左边距、右边距、垂直边距
另有$margin_t与$margin_b与$margin_v等价,分别指top、bottom、vertical,但此三者值绝对一致

$syln为该行有的音节数量

template syl

参考自适应变量,在syl下会有:
$stop  $sbottom  $sleft  $sright  $scenter  $smiddle  $swidth  $sheight  $sdur  $sstart  $send  等

没有仅syl内联变量

但是在template syl中也可使用template line中的内联变量,以获取syl所在line的各个数值
所以实际template syl中可以用的内联变量会更多

使用参考

Comment: 0,0:00:00.00,0:00:00.00,Default,,0,0,0,template line,{\fs100\move($lleft,$lmiddle,$lcenter,$lmiddle)\t(0,$dur,\blur$syln)}
Comment: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,karaoke,{\k50}参考{\k30}文{\k70}字

生成:
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\fs100\move(924,1060,960,1060)\t(0,500,\blur3)}参考{\fs100\move(924,1060,960,1060)\t(0,300,\blur3)}文{\fs100\move(924,1060,960,1060)\t(0,700,\blur3)}字

Comment: 0,0:00:00.00,0:00:00.00,Default,,0,0,0,template syl,{\pos($scenter,$smiddle)\alpha&HFF&\t($sstart,$mid,\alpha&H00&)}
Comment: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,karaoke,{\k50}参考{\k30}文{\k70}字

生成:
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(924,1060)\alpha&HFF&\t(0,0,\alpha&H00&)}
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(942,1060)\alpha&HFF&\t(0,250,\alpha&H00&)}参考
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(969,1060)\alpha&HFF&\t(500,650,\alpha&H00&)}文
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(987,1060)\alpha&HFF&\t(800,1150,\alpha&H00&)}字

简单计算式及使用函数

以下均指template行下的用法!

即便有了内联变量,我们其实也做不了什么,内联变量提供的坐标值等数据应该是为实际需要特效做基础的
比如可能需要中央横坐标减50,需要1/2的dur等

在template行中使用英文半角感叹号(!)包裹计算式或函数,在生成fx行时会运行该计算式或函数

如:
Comment: 0,0:00:00.00,0:00:00.00,Default,,0,0,0,template line,{\pos(!$scenter-50!,$smiddle)\t(!$dur/2!,$dur,!math.random(1,5)!,\alpha&HFF&)}
Comment: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,karaoke,{\k50}参考{\k30}文{\k70}字
生成:
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(892,1060)\t(250,500,3,\alpha&HFF&)}参考{\pos(919,1060)\t(150,300,4,\alpha&HFF&)}文{\pos(937,1060)\t(350,700,3,\alpha&HFF&)}字

code行中的lua不能换行,只能敲空格

数据类型

nil

空值,经典null、undefined

该值为空或未定义时,均为nil

可用于删除table中的值

boolean

布尔值,true或false

1==1即返回true,1=="a"即返回false

number

数字,准确而言是double

1、2、3、1.5、-1.5、2333
应该不用多解释了

string

字符串

"a"、'極彩花夢'、"2333"、"萌え萌えキュン"均为字符串
需要英文双引号/英文单引号包裹
或者[[内容]]这样包裹

table

表,实际也就是数组

容纳一些其他类型的数据

构造:a={}
构造并初始化:a={1, 2.5, "極彩花夢", true}

非常逆天的是,lua的table的索引是从1开始的,是从1开始的!
不是从0开始

function

函数

function isEven(x) return (x%2 == 0) and 1 or 0 end
使用时isEven(2)会返回1,isEven(3)会返回0

构造:function 函数名(传入值)  …… return 输出值 end

有一些可以直接用的函数,比如math.random()可以取随机数

lua算术运算符

+,即相加,如!30+80!会输出110

-,即相减,如!30-80!会输出-50;如果没有被减数,即将减数取负

*,即相乘,如!30*80!会输出2400

/,即相除,如!30/80!会输出0.375

%,取余,如!11%3!,会输出11/3后除不尽的部分,9/3可以整除,故会输出2(即11-9的结果)

^,乘幂,如!2^3!,会输出2*2*2得出的8

另,//一般不可用

lua关系运算符

==,是否等于,相等则返回true,否则false
如!(1=="a") and 1 or 0!会返回0

~=,是否不等于,与==相反,相当于其他语言的!=

>,是否大于,是则返回true,否则false,如!(1>2) and 1 or 0!会返回0
>=,是否大于等于
<,是否小于
<=,是否小于等于

lua逻辑运算符

and,与,但同其他语言的&&差距过大

or,或,但与其他语言的||差距过大

not,非,与其他语言的!差距不大

not取非还是比较容易理解的,但
lua的and和or是真的逆天

a and b,若a为true,表达式值则取b
a or c,若a为false,表达式值则取c

a and b or c,若a为true,则表达式取b,若a为false,则表达式取c
如【!isEven(3) and 1 or 0!】其中isEven为前文中的判断是否偶数的函数,则此处值会取0

lua其它运算符

..,连接字符串,如【"m 0 0 b -3 0 -5 2 -5 5 b -5 8 -3 10 0 10 b 3 10 5 8 5 5 b 5 2 3 0 0 0 ".."m 20 0 b 17 0 15 2 15 5 b 15 8 17 10 20 10 b 23 10 25 8 25 5 b 25 2 23 0 20 0"】会输出【m 0 0 b -3 0 -5 2 -5 5 b -5 8 -3 10 0 10 b 3 10 5 8 5 5 b 5 2 3 0 0 0 m 20 0 b 17 0 15 2 15 5 b 15 8 17 10 20 10 b 23 10 25 8 25 5 b 25 2 23 0 20 0】

#,返回字符串或表的长度,如#"極彩花夢"会输出12,#"KyokuSai"会输出8,真是极其合理呢()

\,转义符,由于ass标签是\开头的,所以在lua的字符串中要输出含有\时需要再加一个\提供转义功能
如要输出"\blur4"则需要写为"\\blur4"

lua函数

aegisub中内置了lua的String和math两个库

string.len(str)以获取字符串长度

string.format(str, …)以格式化字符串
如string.format("m %d %d l %d %d l %d %d l %d %d ",-5,-5,5,-5,5,5,-5,5)会输出m -5 -5 l 5 -5 l 5 5 l -5 5
常用的情况:
%d接收数字并转为整数
%f接收数字并转为浮点数(默认保留6位小数并由0填充),如果需要用0填充并保留2位小数则用%0.2f
%s接收字符串
%x接收数字并转化为16进制小写,%X接收数字并转化为16进制大写

string.upper(str)以转化为大写
string.lower(str)以转化为小写

string.reverse(str)将字符串反转

string.sub(str, start [, end])以截取字符串,end为可选参数,默认为-1(即截取到末尾)
如string.sub("極彩花夢",4)会返回"彩花夢",string.sub("KyokuSai",6,9)会返回"Sai"

string.find(str, search [, init [, plain]])以查找字符串,init和plain均为可选参数
search为要查找的字符串,默认为正则表达式,如果您不知道这是什么意义,可以考虑将plain设为true
init指定搜索的起始位置
plain为是否关闭正则匹配,默认为false即开启正则表达式,设为true则关闭
如【string.find("KyokuSaiYume","u")】【string.find("KyokuSaiYume","u",6)】分别输出5、10
【string.find("KyokuSaiYume","[A-Z]",2)】【string.find("KyokuSaiYume","[A-Z]",2,true)】分别输出6、nil
正则表达式:过于繁杂,如有兴趣请自行了解

string.gsub(str, find, replace [, num])以替换字符串,num为可选参数
find为要找的字符串(正则表达式),replace为想要替换成的字符串,num指定次数(默认全部替换)
类似于上述的string.find,使用如【string.gsub("KyokuSaiYume","[A-Z][^A-Z]*$","Sub")】输出"KyokuSaiSub"

string.rep(str, num)以重复字符串
如string.rep("123",2)输出"123123"

math.ceil(num)以对数字取整,math.ceil(2.333)输出3
math.floor为向下取整

math.max(num1, num2, …)以取传入数字中的最大值

math.min(num1, num2, …)以去传入数字中的最小值

math.random(num1 [, num2])以取随机数
如math.random(100)为取1到100的随机整数(不是从0开始),math.random(-1,1)以取-1到1的随机整数
传入值一个为小数时将其向上取整一次,两个皆为小数时寄

math.abs(num)以取绝对值

另有math.sin  math.tan  math.acos  等等,如有兴趣请自行参考

_G.util

即使用util.lua下提供的函数
以下_G.util.XXX部分可写作_G.XXX

_G.util.ass_color(r, g, b)

返回ass中的颜色字符串

r、g、b请取0-255以内的值,分别对应红red、绿green、蓝blue
如【_G.util.ass_color(0,0,0)】会返回"&H000000&",即纯白

_G.util.ass_alpha(a)

返回ass中的透明度字符串

a请取0-255以内的值
如【_G.util.ass_alpha(255)】会返回"&HFF&",即透明

_G.util.ass_style_color(r, g, b, a)

返回ass中的颜色字符串

上述两个函数的组合,经典rgba组合——但
输出(&HAABBGGRR)不能直接使用

_G.util.extract_color(str)

根据输入str返回对应值

str可以是:&HAABBGGRR(_G.util.ass_style_color的输出)
可以是:&HBBGGRR&(常规ass颜色)
可以是:&HAA&(常规ass透明度)
可以是:#RRGGBBAA(网络编码html下的rgba颜色)

如【r, g, b, a = _G.util.extract_color("&H00ABCDEF&")】则r、g、b、a分别为239、205、171、0

_G.util.alpha_from_style(str)

返回ass中的透明度字符串

str可以是:&HAABBGGRR(_G.util.ass_style_color的输出)
可以是:&HBBGGRR&(常规ass颜色)
可以是:&HAA&(常规ass透明度)
可以是:#RRGGBBAA(网络编码html下的rgba颜色)

如【a = _G.util.alpha_from_style("&H00ABCDEF&")】则a为"&H00&"

_G.util.color_from_style(str)

返回ass中的颜色字符串

str可以是:&HAABBGGRR(_G.util.ass_style_color的输出)
可以是:&HBBGGRR&(常规ass颜色)
可以是:&HAA&(常规ass透明度)
可以是:#RRGGBBAA(网络编码html下的rgba颜色)

如【 r, g, b= _G.util.alpha_from_style("&H00ABCDEF&")】则r、g、b分别为239、205、171

_G.util.HSV_to_RGB(h, s, v)

返回rgb三个参数

HSV颜色模型中,H指色相Hue,S指饱和度Saturation,V指明度Value
当然一两个字也不好解释HSV是个什么样子的,具体使用时可能还是找下工具直观看比较方便

h取0-360,s取0-1,v取0-1

Comment: 0,0:00:00.00,0:00:00.00,Default,,0,0,0,template syl noblank,!retime("syl2end",0-$dur,0)!{\pos($scenter,$smiddle)\3c!_G.ass_color(_G.HSV_to_RGB($si/$syln*360,1,1))!\blur4\an5\fscx100\fscy0\t(0,$dur,\fscx80\fscy120\t($dur,!$dur*1.2!,\fscx100\fscy100))}
Comment: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,karaoke,{\k40}萌{\k40}え{\k40}萌{\k40}え{\k40}キ{\k40}ュ{\k40}ン{\k40}で{\k40}す

生成:
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\pos(651,950)\3c&H00AAFF&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}萌
Dialogue: 0,0:00:00.40,0:00:05.00,Default,,0,0,0,fx,{\pos(727,950)\3c&H00FFAA&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}え
Dialogue: 0,0:00:00.80,0:00:05.00,Default,,0,0,0,fx,{\pos(804,950)\3c&H00FF00&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}萌
Dialogue: 0,0:00:01.20,0:00:05.00,Default,,0,0,0,fx,{\pos(881,950)\3c&HAAFF00&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}え
Dialogue: 0,0:00:01.60,0:00:05.00,Default,,0,0,0,fx,{\pos(958,950)\3c&HFFAA00&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}キ
Dialogue: 0,0:00:02.00,0:00:05.00,Default,,0,0,0,fx,{\pos(1036,950)\3c&HFF0000&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}ュ
Dialogue: 0,0:00:02.40,0:00:05.00,Default,,0,0,0,fx,{\pos(1113,950)\3c&HFF00AA&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}ン
Dialogue: 0,0:00:02.80,0:00:05.00,Default,,0,0,0,fx,{\pos(1191,950)\3c&HAA00FF&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}で
Dialogue: 0,0:00:03.20,0:00:05.00,Default,,0,0,0,fx,{\pos(1268,950)\3c&H0000FF&\blur4\an5\fscx100\fscy0\t(0,400,\fscx80\fscy120\t(400,480,\fscx100\fscy100))}す

效果图:

非常简单,但却非常优秀的效果
其中用到了retime,将在下文说明

_G.util.trim(str)

输出去掉首尾空格后的字符串
不能省略掉util

如【_G.util.trim(" 極 彩 花 夢 ")】输出"極 彩 花 夢"

_G.util.headtail(str)

输出由字符串中首个空格分割开的前后两部分字符串
不能省略掉util

如【a, b = _G.util.headtail("極彩 花夢")】则a、b分别为"極彩""花夢"

_G.util.words

需要用到for循环
不能省略掉util

for word in util.words(str) do  end
如【local res="" for a in _G.util.words("極 彩 花 夢") do res=res..a end】则res为"極彩花夢"

_G.util.clamp(inval, min, max)

如果inval<min则返回min,min<inval<max则返回inval,max<inval则返回max

如【_G.util.clamp(1, 5, 10)】则返回5
【_G.util.clamp(7, 5, 10)】则返回7
【_G.util.clamp(17, 5, 10)】则返回10

_G.util.interpolate(t, a, b)

实际相当于(a+b)*t
但是当t取(-∞,0)时,返回a,t取(1,+∞)时,返回b

_G.util.interpolate_color(t, color1, color2)

与_G.util.interpolate近似

但输入color1和color2为颜色字符串,返回ass颜色字符串
color1和color2可以取ass颜色字符串,也可以取网络编码html下的#RRGGBB

_G.util.interpolate_alpha(t, alpha1, alpha2)

同上

额外

此处考虑写额外一篇或者后续补充

额外函数

此处或尚待修改

remember(name, value [, condition])  recall(name [, default])

虽然code行中可以直接设变量,但template行终归用着不方便
而这两个函数则是用于解决这个问题的

例如【\fscx!remember("fsc",math.random(50,80))!\fscy!recall.fsc!\t(0,!$dur*.8!,\fscx!200-recall("fsc")!\fscy!recall("fsc",math.random(120,150))!\t(!$dur*.8!,$dur,\fscx100\fscy100))】
remember(name, value [, condition]),condition为条件
recall有三种形式:recall.name、recall("name")、recall("name", default),其中default为值是nil时取的值

maxloop(num)

等价于loop修饰语
但可以设定值为计算式或函数等

用j获取当前是第几次循环

Comment: 0,0:00:00.00,0:00:00.00,Default,,0,0,0,template line,!maxloop(remember("loop",16))!{\an3\pos($lright,$lbottom)\clip(0,!$ltop+(j-1)/recall.loop*$lheight!,$lright,!$ltop+j/recall.loop*$lheight!)\fsp!j*3!\t(0,300,1.6,\fsp0)}
Comment: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,karaoke,萌え萌えキュンです

生成(前4行):
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\an3\pos(1307,1000)\clip(0,900,1307,906.25)\fsp3\t(0,300,1.6,\fsp0)}萌え萌えキュンです
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\an3\pos(1307,1000)\clip(0,906.25,1307,912.5)\fsp6\t(0,300,1.6,\fsp0)}萌え萌えキュンです
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\an3\pos(1307,1000)\clip(0,912.5,1307,918.75)\fsp9\t(0,300,1.6,\fsp0)}萌え萌えキュンです
Dialogue: 0,0:00:00.00,0:00:05.00,Default,,0,0,0,fx,{\an3\pos(1307,1000)\clip(0,918.75,1307,925)\fsp12\t(0,300,1.6,\fsp0)}萌え萌えキュンです

效果图:

retime(mode, startadjust, endadjust)

用于修改开始时间与结束时间

官方的这张图解释得非常清晰了

在本篇的开头有一段打了K轴的歌词,但是在应用template syl后每个字的开始时间、结束时间仍然是原行的开始时间、结束时间
当然,基础的目的就是调整syl的开始时间为K轴计算后的

最典型的也就是!retime("syl2end",0,0)!,这样会使syl的开始时间修正为K轴计算后的

前文还有一处用到了retime,是retime("syl2end",0-$dur,0)
因为对象是syl,所以$dur是音节的持续时间,即相当于上图中的presyl到postline这一段时间,也是比较常用的时间段

relayer(n)

修改层数

其余的

或许后续会修改补充此处
但是以上的函数已经满足绝大部分需求了

结束语

本篇是当前最为不完善的,可能在后续会不断修改

并且已经确实不适用于单纯的入门了,即便作为例子的部分也都没有保持“简练”,甚至部分算得上故意的复杂(毕竟正常人哪会犯得着还用正则表达式)

而且许多确实不是只言片语就能解释的,就算解释了也多半只会囿于“解释”
就比如正则表达式,要真解释起来就是一堆一堆规则,看一遍哪会记得住还会用

且后续可能会删掉其中一些赘余部分
比如极多的重复意义的函数、变量,或者极其难用的东西
只是单纯的难为人去使用,而得到的价值还让人难以评价,作为工具确实是该抛弃的那类

那么,让我们带着这些做一些简单的特效吧!(

空白

少女还未记录主人的信息,或许需要登录……