ASS字幕时间调整

最近得了「弹幕依赖症」,看视频时没有弹幕总觉得哪里不对劲,之前写过拿弹幕文件的东西,再配合转换XML弹幕为ASS,本来基本就完事的,不过这一次,因为分Part了,两个XML都是从Part的00:00.00开始计时的,而在网上下载的原始视频是完整的,于是就需要调整第二个ASS文件的时间。

这里每个弹幕文件里面都有8000条,人工调整当然是想都没想过,想的是用什么语言来写个快速调整ASS字幕时间的,C/C++虽然处理很快,但是,果然呢,说到文字处理,那为何不用Perl呢。

于是说做就做,这里就仅仅是针对使用了转换XML弹幕为ASS的ASS文件,不过其实要改成通用的,也只需要改一小部分即可。直接贴代码啦。

Code

#!/usr/bin/env perl

use strict;
use warnings;
use utf8;
use 5.010;

use Getopt::Long;

sub colon_time_to_second {
        my \$time = shift || return 0;
        my @component = split':',\$time;
        return if (\$#component != 2);
        \$component[0] * 3600 + \$component[1] * 60 + \$component[2];
}

sub second_to_colon_time {
        my \$seconds = shift;
        my \$component1 = int(\$seconds / 3600);
        my \$component2 = sprintf"%02d", (int((\$seconds - \$component1 * 3600) / 60));
        my \$component3 = sprintf"%05.2f",(\$seconds - \$component1 * 3600 - \$component2 * 60);
        "\$component1:\$component2:\$component3";
}

sub shift_timeline {
        my \$orig = colon_time_to_second shift;
        my \$shift = shift || 0;
        second_to_colon_time \$orig + \$shift;
}

sub shift_file_name {
        my \$filename = shift;
        my @paths = split'/',\$filename;
        my \$filepath = \$paths[\$#paths];
        my @dots = split /./,\$filepath;
        if (\$#dots > 0) {
                my \$shift_name = "";
                for(my \$i = 0; \$i < \$#paths; \$i++){
                        \$shift_name .= \$paths[\$i];
                        \$shift_name .= "/";
                }
                for (my \$i = 0; \$i < \$#dots; \$i++) {
                        \$shift_name .= \$dots[\$i];
                        \$shift_name .= ".";
                }
                \$shift_name .= "shift.".\$dots[\$#dots];
        } else {
                my\$shift_name = "";
                for(my\$i = 0; \$i < \$#paths - 1; \$i++){
                        \$shift_name .= \$paths[\$i];
                        \$shift_name .= "/";
                }
                \$shift_name .= "_shift";
        }
}

my@all_file = ();
my\$shift_time;

GetOptions(
        'file|f=s{,}'=> @all_file,
        't=s'             => \$shift_time
);

foreach my \$file (@all_file) {
        next if (!-f -e \$file);
        open (my\$ASSFILE ,\$file);
        my \$shift_file_name = shift_file_name \$file;
        open my \$CONVERT, ">\$shift_file_name"ordie"cannot open \$shift_file_namen";
        while (<\$ASSFILE>) {
                if (/Dialogue: 2,(.*),Danmaku2ASS(.*)/) {
                        my @time = split ',',\$1;
                        print \$CONVERT"Dialogue: 2,";
                        print \$CONVERT shift_timeline \$time[0], \$shift_time;
                        print \$CONVERT",";
                        print \$CONVERT shift_timeline \$time[1], \$shift_time;
                        print \$CONVERT",Danmaku2ASS";
                        print \$CONVERT\$2;
                }else {
                        print \$CONVERT\$_;
                }
        }
        say"OK! Saved at \$shift_file_name";
}
say"[All Done]";

Leave a Reply

Your email address will not be published. Required fields are marked *

four + five =