找回密码
 立即注册
查看: 521|回复: 0

[Aegisub] kara-templater一些奇技淫巧的分享

  • TA的每日心情
    无聊
    2023-3-18 18:33
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    26

    主题

    328

    回帖

    1056

    VC币

    星辰大海

    Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20

    积分
    418206
    Lambholl 发表于 2026-1-19 17:07:47 | 显示全部楼层 |阅读模式
    本帖最后由 Lambholl 于 2026-1-19 23:13 编辑

    先声明一下,我使用的kara-templater是AegisubDC版本中的修改版,因此有一些特性不一样,比如可以使用原版不能用的code char noblank等。
    这个改版templater我认为还是挺好用的,因为《大神之路》这类教程告诉你可以用char,可以用noblank,实际上这两个一起用的需求我认为也不小。

    为什么写这个帖子呢,因为期末考复习疯了,想来放松一下,虽然这种帖子应该没什么人看
    以后也可能会更一些别的思路(下次期末考?)总之先写这个吧

    在line模板执行过程中,提前获取下一行的宽度

    具体有什么应用呢?个人应用在 BV1tF4m1u7FFBV1GJkeBdEke的0:25-1:03 中。
    这里一个用的是\frx旋转字幕,同时在开始和结束处用\fscx调整宽度,让两行的宽度在旋转时能够无缝衔接。
    另一个是用来给横向\t \clip来制作「扫描」的效果,同时为了给「扫描」过程加上加速度(先加速再减速,转场动画的常见处理方式),需要取两行中较宽的一个数字作为clip起点和终点。

    知周所众,想要当前行的宽度能被下一行读到,只需要使用code once初始化一个数组,在code line中把当前行的line.width加进去就行了。
    但是要读取下一行,就没有提供这种方法了。

    翻阅官方文档的执行顺序可以知道,在执行完所有的code once之后,会按顺序扫描所有的待处理行,如果是应该被执行模板的行(特效栏为空且非注释行|特效栏为karaoke),执行所有匹配的code line和template line

    也就是说,模板执行是按待处理行出现的顺序执行的,例如我们有这几行:
    1. Comment: 0,0:02:09.29,0:02:12.22,OP-JP3,,0,0,0,karaoke,これから何回も何回も何回も
    2. Comment: 0,0:02:12.22,0:02:15.06,OP-JP3,,0,0,0,karaoke,何回も季節は巡る
    3. Comment: 0,0:02:15.06,0:02:18.20,OP-JP3,,0,0,0,karaoke,そのたび何回も何回も何回も
    4. Comment: 0,0:02:18.20,0:02:21.03,OP-JP3,,0,0,0,karaoke,君とこの場所に
    5. Comment: 0,0:02:21.03,0:02:27.01,OP-JP3,,0,0,0,karaoke,月は輝き 星は瞬く
    6. Comment: 0,0:02:27.01,0:02:32.91,OP-JP3,,0,0,0,karaoke,その身果てるまで照らせるように
    复制代码
    将OP-JP3复制一遍,再把这几行复制一遍:
    1. Comment: 0,0:02:09.29,0:02:12.35,OP-JP3_2,,0,0,0,karaoke,これから何回も何回も何回も
    2. Comment: 0,0:02:09.29,0:02:12.35,OP-JP3_2,,0,0,0,karaoke,これから何回も何回も何回も
    3. Comment: 0,0:02:12.35,0:02:15.06,OP-JP3_2,,0,0,0,karaoke,何回も季節は巡る
    4. Comment: 0,0:02:15.06,0:02:18.26,OP-JP3_2,,0,0,0,karaoke,そのたび何回も何回も何回も
    5. Comment: 0,0:02:18.26,0:02:21.03,OP-JP3_2,,0,0,0,karaoke,君とこの場所に
    6. Comment: 0,0:02:21.03,0:02:27.01,OP-JP3_2,,0,0,0,karaoke,月は輝き 星は瞬く
    7. Comment: 0,0:02:27.01,0:02:32.91,OP-JP3_2,,0,0,0,karaoke,その身果てるまで照らせるように
    8. Comment: 0,0:02:27.01,0:02:32.91,OP-JP3_2,,0,0,0,karaoke,その身果てるまで照らせるように
    9. Comment: 0,0:02:09.29,0:02:12.22,OP-JP3,,0,0,0,karaoke,これから何回も何回も何回も
    10. Comment: 0,0:02:12.22,0:02:15.06,OP-JP3,,0,0,0,karaoke,何回も季節は巡る
    11. Comment: 0,0:02:15.06,0:02:18.20,OP-JP3,,0,0,0,karaoke,そのたび何回も何回も何回も
    12. Comment: 0,0:02:18.20,0:02:21.03,OP-JP3,,0,0,0,karaoke,君とこの場所に
    13. Comment: 0,0:02:21.03,0:02:27.01,OP-JP3,,0,0,0,karaoke,月は輝き 星は瞬く
    14. Comment: 0,0:02:27.01,0:02:32.91,OP-JP3,,0,0,0,karaoke,その身果てるまで照らせるように
    复制代码
    于是,在执行模板的过程中,就会先执行上面 OP-JP3_2 的模板,再执行下面 OP-JP3 的模板。
    上面的 OP-JP3_2 不写template,只写code把自己的宽度存进去即可,下面的 OP-JP3 就可以读取它上下一行的宽度。
    这里将头尾两行各复制一遍,是为了更轻松地处理边界情况,即第一行读取上一行的宽度、最后一行读取下一行的宽度,都能读到自身的宽度,这样在相应进行\fscx的时候,就可以自然计算出\fscx100
    当然,也可以选择在读取的代码中加if i<=1,if i>=#arrayWidth 来进行处理,这样处理更加低耦合、高内聚,是更好的写法。

    那么按照上述思路,我的代码就变成了:
    1. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3_2,,0,0,0,code,len_3_jp = {}
    2. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3_2,,0,0,0,code line,table.insert(len_3_jp, line.width)
    3. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,i3jp = 1
    4. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,function getLen3(mode) local result = len_3_jp[i3jp+mode+1] if mode==1 then i3jp=i3jp+1 end return result end
    5. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,code,function getPercent3(mode) local len1 = getLen3(mode) local len2 = getLen3(mode+1) local lenT = {len1,len2} local perc = (len1+len2)/lenT[1-mode]/2*100 return perc end
    6. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,template line,!restyle('OP-JP2')!{\blur3\an5\pos($lcenter,$lmiddle)\frx90\fscx!getPercent3(-1)!\t(0,120,0.75,\frx0\fscx100)\t(!$ldur-120!,!$ldur!,1.33,\frx-90\fscx!getPercent3(0)!)}
    7. Comment: 0,0:00:00.00,0:00:00.00,OP-JP3,,0,0,0,,
    复制代码
    首先用 len_3_jp 存储 OP-JP3_2 每一行的宽度,然后 OP-JP3 就能读取了,指针是 i3_jp
    为了减少代码冗余,这里 getLen3 用 mode 来进行区分读取的是上一行还是下一行。在里面给索引的指针+1([i3jp+mode+1])是因为第一行重复了一遍,因此索引的指针应该+1。
    下面的 getPercent3 实际模拟的就是一个窗口,读取第 i+mode 行和 i+mode+1 行的宽度计算,因此计算上一行和这一行的平均宽度时,mode=-1,计算这一行和下一行时,mode=0

    大概就是如此,写了这么多,也不知道也没有说明白,如有纰漏请指出(


    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    快速回复 返回顶部 返回列表