javascriptphpjqueryregexsrt

Adding or substracting seconds from a .SRT file


I've searched and found nothing similar.
What I'm trying to achieve is creating a simple PHP/js/jq script that can add or subtract seconds from a .srt file. I'm not sure if regex is something I should go with to achieve it or something else.
The user will upload/copy the text of the srt file and then add the number of seconds to an input box that they want to add or subtract seconds from SRT.

For example if user adds +4 seconds to the following srt file:

0
00:00:04,594 --> 00:00:10,594
this is a subtitle

1
00:00:40,640 --> 00:00:46,942
this is another subtitle

2
00:02:05,592 --> 00:02:08,694
this is one more subtitle

It should look like this:

0
00:00:08,594 --> 00:00:14,594
this is a subtitle

1
00:00:44,640 --> 00:00:50,942
this is another subtitle

2
00:02:09,592 --> 00:02:12,694
this is one more subtitle

Solution

  • Here's a solution in PHP, which is one of your specified languages.

    If you can represent the time offset that you want to apply as a string the you can use DateTime methods DateTime::modify(), DateTime::createFromFormat() and preg_replace_callback() to achieve what you want to do.

    The SubRip Wikipedia entry specifies the timecode format as:

    hours:minutes:seconds,milliseconds

    So we can write a regex to capture this; e.g: /(\d+:\d+:\d+,\d+)/ - although you might wish to refine this.

    Given a scenario where your .srt file is read into a string $srt, and you want to increase the times by 5 seconds:

    <?php
    
    $srt = <<<EOL
    
    0
    00:00:04,594 --> 00:00:10,594 this is a subtitle
    
    1
    00:00:40,640 --> 00:00:46,942 this is a subtitle
    
    2
    00:02:05,592 --> 00:02:08,694 this is a subtitle
    EOL;
    
    $regex  = '/(\d+:\d+:\d+,\d+)/';
    $offset = '+5 seconds';
    
    $result = preg_replace_callback($regex, function($match) use ($offset) {
        $dt = DateTime::createFromFormat('H:i:s,u', $match[0]);
        $dt->modify($offset);
        return $dt->format('H:i:s,u');
    }, $srt);
    
    echo $result;
    

    On each $match, use DateTime::createFromFormat() to convert the matching timecode into a DateTime object, which you can then modify and reformat as a string representing the offset time.

    You can use a variety of offset values with DateTime::modify() including, but not limited to: +1 minute, -30 seconds, 1 hour 2 minutes and so on. Read the linked documentation for more details.

    This yields:

    0
    00:00:09,594000 --> 00:00:15,594000 this is a subtitle
    
    1
    00:00:45,640000 --> 00:00:51,942000 this is a subtitle
    
    2
    00:02:10,592000 --> 00:02:13,694000 this is a subtitle
    

    Hope this helps :)