13

Please see this question.

I have just merged two avi files cd1.avi and cd1.avi into movie.avi using:

avimerge -o movie.avi -i cd{1,2}.avi

Problem is that I had to subtitle files linked to the first avi files:

cd1.srt
cd2.srt

At first I tried simply to concatenate the files together:

cat cd{1,2}.srt > movie.srt

But that caused havoc with the subtitles... any suggestions?

4 Answers 4

20

This is pretty trivially done, since .srt files are just text files that contain time stamps -- all you need to do is add the length of cd1.avi to the times of all the subtitles in cd2.srt. You can find the length of cd1.avi with ffmpeg:

ffmpeg -i cd1.avi  # Look for the Duration: line

And then add that to cd2.srt using srttool

srttool -d 12345 -i cd2.srt  # 12345 is the amount to add in seconds

or:

srttool -a hh:mm:ss -i cd2.srt  # The first subtitle will now start at hh:mm:ss

Then you should just be able to concatenate the files together and renumber:

srttool -r -i cd.srt

I picked srttool because in Arch it comes with transcode, which you installed for this question; there are lots of other tools that can shift and merge .srt files too, and at least one website, submerge

4
  • +1 thanks micheal, really appreciate your efforts with my questions
    – Stefan
    Commented Sep 20, 2010 at 22:15
  • 2
    Thanks! This worked great. Only problem I found is that srttool puts output to the command line. I actually doesn't modify the file you want. A little redirection (>) and WHAMMO, it works perfectly. This has been a huge help and thank you very much.
    – user11667
    Commented Oct 19, 2011 at 4:38
  • 1
    How do you install srttool on MacOS? Commented Jul 21, 2020 at 12:36
  • ffmpeg can do that too. use itsoffset to delay s1. v0=0.mkv; s0=0.srt; s1=1.srt; d0=$(ffprobe -i "$v0" -loglevel 0 -show_entries format=duration -of default=nw=1:nk=1); { cat "$s0"; echo; echo; ffmpeg -hide_banner -loglevel error -itsoffset "$d0" -i "$s1" -f srt -; } | ffmpeg -hide_banner -loglevel error -i - out.srt
    – milahu
    Commented May 22 at 7:36
0

I needed the subs from the second SRT file to be appended to the nearest EXISTING timing in the first SRT file, so came up with the script below.

For example, in this way you can join subtitles in different languages into a single file. You might also want to modify the script and append content from the other file with a different color. The only supported syntax for doing this in a SRT file is using something like <font color="#00ffff">text here</font>.

The script requires a recent python3 and the srt module which can be installed with pip3 install srt.

Usage:

python3 merge_srt.py first.srt second.srt
#!/usr/bin/env python3

import argparse
import sys
from datetime import timedelta
from pathlib import Path

# pip3 install srt
import srt


def nearest(items, pivot):
    return min(items, key=lambda x: abs(x.start - pivot))


if __name__ == '__main__':

    parser = argparse.ArgumentParser(description='merge SRT subtitles',
                                     usage="""
    Merge SRT subtitles:                                     
    \t{0} first.srt second.srt -o merged.srt
 """.format(Path(sys.argv[0]).name))

    parser.add_argument('srt1',
                        metavar='srt1',
                        help='SRT-file-1')
    parser.add_argument('srt2',
                        metavar='srt2',
                        help='SRT-file-2')
    parser.add_argument('--output-file', '-o',
                        default=None,
                        help='Output filename')
    parser.add_argument('--encoding', '-e',
                        default=None,
                        help='Input file encoding')
    args = parser.parse_args(sys.argv[1:])

    srt1_path = Path(args.srt1)
    srt2_path = Path(args.srt2)

    with srt1_path.open(encoding=args.encoding or 'utf-8') as fi1:
        subs1 = {s.index: s for s in srt.parse(fi1)}

    with srt2_path.open(encoding=args.encoding or 'utf-8') as fi2:
        subs2 = {s.index: s for s in srt.parse(fi2)}

    # iterate all subs in srt2 and find the closest EXISTING slots in srt1
    for idx, sub in subs2.items():

        start: timedelta = sub.start
        sub_nearest_slot: srt.Subtitle = nearest(subs1.values(), start)
        sub_nearest_slot.content = f'{sub_nearest_slot.content}<br>{sub.content}'
        subs1[sub_nearest_slot.index] = sub_nearest_slot

    if not args.output_file:
        generated_srt = srt1_path.parent / (f'{srt1_path.stem}_MERGED_{srt1_path.suffix}')
    else:
        generated_srt = Path(args.output_file)

    with generated_srt.open(mode='w', encoding='utf-8') as fout:
        fout.write(srt.compose(list(subs1.values())))
2
  • 1
    srt works in 95% of all cases. pysubs2 is a generic subtitles parser for python
    – milahu
    Commented May 22 at 7:11
  • srt never failed me, and when the original srt files are not compliant it includes srt-normalize, srt-deduplicate etc; but good to know there are other options that are actively developed and maintained, especially with support for other formats than srt
    – ccpizza
    Commented May 22 at 15:53
0

I liked the accepted answer. Unfortunately, it depended on (a) an invocation of ffmpeg that exited with a non-zero exit code and (b) on srttool, which is not obviously available in homebrew.

Additionally, I was wanting something that would perform a bit more automation over several files (since I'm using a DJI drone and it splits files every 4GB).

I ended up writing srt-concat as part of the jaraco.media project. It does require a Python environment (and the expertise that requires), but it's readily installable and runnable. Just pip install jaraco.media into your Python environment, then run python -m jaraco.media.srt-concat ... according to the directions in that readme. It will attempt to detect the media file associated with each matching SRT file, calculate the durations of those files, and add the aggregated duration as it concatenates the SRT entries.

0

The accepted answer uses ffmpeg and then srttool. If you already have ffmpeg installed, you can just use the concat demuxer and don't need anything else:

$ cat mylist.txt
file '/path/to/file1.srt'
file '/path/to/file2.srt'
file '/path/to/file3.srt'
    
$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.srt
1
  • no, video is longer than subtitles, so the offset is wrong. see my other comment with itsoffset
    – milahu
    Commented May 22 at 7:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .