6

In bash I don't know how to do that. I need to do a bash-script. At stdin I have .srt file of subtitles in this format:

num HH:MM:SS,SSS --> HH:MM:SS,SSS text line 1 text line 2 ... 

HH:MM:SS,SSS start and finish of title for text.

Script must shift seconds. (it can be + or -)

Example:

$cat bmt.srt 5 00:01:02,323 --> 00:01:05,572 Hello, my frieds! 6 .... $./shifter.sh +3<mbt.srt 5 00:01:05,323 --> 00:01:08,572 Hello, my frieds! 6 

I need to grab all HH:MM:SS and convert them to seconds firstly. Is somebody able do this without sed?

1
  • mplayer has some subtitle delay options, only I don't know if it can store it as new subtitle; still, I suspect there's an existing solution for this out there somewhere...CommentedOct 17, 2013 at 20:15

2 Answers 2

7

Unless the subtitle file spans more than 24 hours, you can use date for this:

#!/usr/bin/env bash set -o errexit -o noclobber -o nounset -o pipefail date_offset="$1" shift_date() { date --date="$1 $date_offset" +%T,%N | cut -c 1-12 } while read -r line do if [[ $line =~ ^[0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]\ --\>\ [0-9][0-9]:[0-9][0-9]:[0-9][0-9],[0-9][0-9][0-9]$ ]] then read -r start_date separator end_date <<<"$line" new_start_date="$(shift_date "$start_date")" new_end_date="$(shift_date "$end_date")" printf "%s %s %s\n" "$new_start_date" "$separator" "$new_end_date" echo "New date" else printf "%s\n" "$line" fi done 

For some reason you need to use decimal numbers with this, but it works:

$ ./shifter.sh "+3.0 seconds" < bmt.srt 5 00:01:05,323 --> 00:01:08,572 New date Hello, my frieds! 6 
    5

    Perl solution. I did not use any classical time handling module, as miliseconds handling is generally poorly supported.

    #!/usr/bin/perl use warnings; use strict; use constant FACTORS => (60 * 60 * 1000, 60 * 1000, 1000, 1); sub time2ms { my $time = shift; my ($ms, $i) = (0, 0); $ms += (FACTORS)[$i++] * $_ for split /[^0-9]/, $time; return $ms; } sub ms2time { my $ms = shift; my $str = q(); for my $i (0 .. 3) { $str .= sprintf +($i == 3 ? '%03d' : '%02d') . (':', ':', ',', q())[$i], $ms / (FACTORS)[$i]; $ms = $ms % (FACTORS)[$i]; } return $str; } my $diff = 1000 * shift; my $TIME_R = qr/[0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3}/; while (<>) { if (my ($from, $to) = /($TIME_R) --> ($TIME_R)/) { my $i = 0; for my $time ($from, $to) { $time = time2ms($time) + $diff; print ms2time($time), (' --> ', "\n")[$i++]; } } else { print; } } 
    2
    • Thanks for the script! Let me add a small improvement though: In the ms2time loop, if $i==3, sprintf should be '%03d' instead of '%02d'.CommentedJan 6, 2014 at 20:07
    • @VangelisTasoulas: Updated.
      – choroba
      CommentedFeb 12, 2017 at 17:11

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.