Como converter um arquivo de legenda .txt para o formato .srt?

3

Eu tenho um arquivo de legendas, parece com isso:

00:00:44:" Myślę, więc jestem".|Kartezjusz, 1596-1650
00:01:01:Trzynaste Pietro
00:01:06:Podobno niewiedza uszczęśliwia.
00:01:10:Po raz pierwszy w życiu|zgadzam się z tym.
00:01:13:Wolałbym...
00:01:15:nigdy nie odkryć|tej straszliwej prawdy.
00:01:19:Teraz już wiem...

Não sei qual formato é esse, mas queria converter as legendas para .srt. Infelizmente, gnome-subtitles e subtitleeditor não reconhecem esse tipo de formato.

gnome-subtitles diz:

Unable to detect the subtitle format. Please check that the file type is supported.

subtitleeditor diz:

Please check that the file contains subtitles in a supported format.

file output:

UTF-8 Unicode text

Existe uma maneira de converter este arquivo para o formato .srt?

    
por Mikhail Morfikov 26.01.2014 / 18:56

2 respostas

4

Isso é muito parecido com a abordagem do @ goldilock, mas, IMO, é mais simples e pode lidar com linhas vazias no arquivo e substitui | por uma quebra de linha:

#!/usr/bin/env perl
my ($time, $text, $next_time, $next_text);
my ($c,$i)=0;
while (<>) {
    ## skip bad lines
    next unless /^\s*([:\d]+)\s*:(.+)/;
    ## If this is the first line. I could have used $. but this is
    ## safer in case the file contains an empty line at the beginning.
    if ($c == 0) {
      $time=$1; 
      $text=$2;
      $c++;
    }
    else {
      ## This is the counter for the subtitle index
      $i++;
      ## Save the current values
      $next_time=$1; 
      $next_text=$2;     
      ## I am assuming that the | should be interpreted
      ## as a newline, remove this if I'm wrong.
      $text=~s/\|/\n/g;     
      ## Print the previous subttitle
      print "$i\n$time,100 --> $next_time,000\n$text\n\n";        
      ## Save the current one for the next line
      $time=$next_time; $text=$next_text;
    }
}     
## Print the last subtitle. It will be dislayed for a minute
## 'cause I'm lazy.
$i++;
$time=~/(\d+:)(\d+)(:\d+)/;
my $newtime=$1 . (sprintf "%02d", $2+1) . $3;
print "$i\n$time,100 --> $newtime,000\n$text\n\n";    

Salve o script como um arquivo e torne-o executável e, em seguida, execute:

./script.pl subfile > good_subs.srt

A saída que recebo na sua amostra foi:

1
00:00:44,100 --> 00:01:01,000
" Myślę, więc jestem".
Kartezjusz, 1596-1650

2
00:01:01,100 --> 00:01:06,000
Trzynaste Pietro

3
00:01:06,100 --> 00:01:10,000
Podobno niewiedza uszczęśliwia.

4
00:01:10,100 --> 00:01:13,000
Po raz pierwszy w życiu
zgadzam się z tym.

5
00:01:13,100 --> 00:01:15,000
Wolałbym...

6
00:01:15,100 --> 00:01:19,000
nigdy nie odkryć
tej straszliwej prawdy.

7
00:01:19,100 --> 00:02:19,000
Teraz już wiem...
    
por 26.01.2014 / 20:44
2

O que Thorsten quis dizer é algo assim:

#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);

my $END = '!!ZZ_END';
my $LastTitleDuration = 5;

my $count = 1;
my $line = <STDIN>;
chomp $line;
my $next = <STDIN>;
while ($line) {
    $next = lastSubtitle($line) if !$next;
    last if !$next;
    chomp $next;
    if (!($next =~ m/^\d\d:\d\d:\d\d:.+/)) { 
        print STDERR 'Skipping bad data at line '.($count+1).":\n$line\n";
        $next = <STDIN>;
        next;
    }
    printf STDOUT
        "%d\r\n%s,100 --> %s,000\r\n%s\r\n\r\n",
        $count++,
        substr($line, 0, 8),
        substr($next, 0, 8),
        substr($line, 9)
    ;
} continue {
    $line = $next;
    $next = <STDIN>;
}

sub lastSubtitle {
    my $line = shift;
    $line =~ /^(\d\d:\d\d:)(\d\d):(.+)/;
    return 0 if $3 eq $END;
    return sprintf("$1%2d:$END", $2 + $LastTitleDuration);
} 

Quando eu envio seus dados de amostra para isso, recebo:

1
00:00:44,100 --> 00:01:01,000
" Myślę, więc jestem".|Kartezjusz, 1596-1650

2
00:01:01,100 --> 00:01:06,000
Trzynaste Pietro

3
00:01:06,100 --> 00:01:10,000
Podobno niewiedza uszczęśliwia.

4
00:01:10,100 --> 00:01:13,000
Po raz pierwszy w życiu|zgadzam się z tym.

5
00:01:13,100 --> 00:01:15,000
Wolałbym...

6
00:01:15,100 --> 00:01:19,000
nigdy nie odkryć|tej straszliwej prawdy.

7
00:01:19,100 --> 00:01:24,000
Teraz już wiem...

Alguns pontos:

  • As legendas realmente começam a décimo segundo atrasado para que não se sobreponham, e porque eu estava com preguiça de adicionar alguma matemática envolvendo o segundo timestamp. Eles então permanecem até 1/10 antes do próximo título.

  • O último título permanece em $LastTitleDuration (5 segundos).

  • Eu usei finais de linha do CRLF de acordo com o artigo da Wikipédia SupRip isso pode não ser necessário.

  • Presume-se que a primeira linha de entrada não esteja malformada. Além disso, eles são verificados e os erros são reportados como stdout, portanto:

    readAlongToSRT.pl < readAlong.txt > whatever.srt
    

    Deve criar o arquivo, mas ainda imprimir erros na tela.

  • O processamento será interrompido em uma linha em branco.

  • Veja o comentário de terdon abaixo re: o possível significado de | no conteúdo das legendas. Você pode querer inserir $line =~ s/|/\r\n/g; antes da linha printf STDOUT .

Isso me levou 20 minutos e os únicos dados de teste que eu tinha eram essas 7 linhas, então não conte com perfeição. Se houver alguma quebra de linha nas legendas , isso causará um problema. Eu presumi que não há; Se esse for o caso, sugiro que você os remova primeiro da entrada, em vez de tentar lidar com eles aqui.

    
por 26.01.2014 / 20:05