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?

Stefan
  • 25,300

4 Answers4

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

Michael Mrozek
  • 93,103
  • 40
  • 240
  • 233
  • +1 thanks micheal, really appreciate your efforts with my questions – Stefan Sep 20 '10 at 22:15
  • 1
    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. –  Oct 19 '11 at 04:38
  • 1
    How do you install srttool on MacOS? – Konrad Szałwiński Jul 21 '20 at 12: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=&quot;&quot;&quot;
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}&lt;br&gt;{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())))

ccpizza
  • 1,723
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

dosentmatter
  • 508
  • 5
  • 12