Skip to content

Node.js. Merge two srt into one srt, with "top-bottom", "time-shift", "finding nearest" and a few more options.

Notifications You must be signed in to change notification settings

ElevenZwei/srt-merge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

srt-merge

Srt-merge is a small node.js project in one hundred lines.
It can merge two srt files into one with some optional options.
It can shift one srt file at given time to match the video file.
It can place one subtitle at the top of screen and another one at bottom that is very useful for language learners.

Usage

You can use this tool in Nodejs or in Bash scripts.
First, npm install or yarn to install dependencies.

By JS Code

Examples are in example.js. Read and run it for a clear understanding.

This project contains one file merge.js, one function merge().

merge(srtPrimary, srtSecondary[, attr, noString])

srtPrimary and srtSecondary accept srt-string, or srt-object in the format of npm-module subtitle. They will not be modified by this function.

attr accepts one of the following values, or an array of them. They describe transformations performed on srtSecondary before it is merge into srtPrimary. The action priority will always be "top-bottom", "move", then "nearest-cue".

Attribute inputs and corresponding effects:

  1. <empty string> or <undefined> or "simple"

    Simply merge two files.

  2. top-bottom

    Place srtPrimary at video bottom, srtSecondary at video top, using ass-file-format tag {\an8} in srt-file output. This feature is supported by many video players including VLC, MPC-HC.

  3. nearest-cue-<threshold>[-no-append]

    Cues in srtSecondary will be appended to corresponding cues in srtPrimary if the difference of their start time is no larger than the given threshold. If srtSecondary has multiple cues within the threshold, srtPrimary will append the earliest one.

    no-append means srtSecondary will only be aligned with srtPrimary within a start time threshold. Whose start time are aligned, whose end time will also be aligned if they are within the threshold.

  4. move-<time shifted>

    srtSecondary will be shifted (can be forward or backward) and merged into srtPrimary.

    noString takes true or false, if it's true, output the srt-object, otherwise output srt text.

If you only want to edit one file, leave the srtPrimary(not srtSecondary) with an empty string.

By Bash

These JS Scripts read options from command line and output to stdout by default. They are helpful in writing bash scripts. Use 'yarn build' to build them, which requires 'yarn global add browserify'.

build/srt-merge.js

This can only accept one attr, not an array of them. When -o <out-file> is not specified, it will output to stdout. -f option means overwrite existing file without prompt. Both input srt files must be text files encoded in utf-8. Piping is under construction.

./srt-merge.js <srt-file-1> [<srt-file-2>] [<one-attr>] [-o [-f(force)] <output Filepath>]

Practical Example

Extracting multiple subtitles from an mkv file and merge them into one

This example is for Windows.

Suppose you want to show subtitles of two languages at the same time, and now both of them are embedded in an MKV video file. You want to extract them out and combine into one.

First, use ffmpeg to check which track is the subtitle you want.

ffmpeg -i <your_mkv_file>

You will see something like:

Stream #0:10(eng): Subtitle: subrip
Metadata:
title : English [Forced]

That means subtitle English[Forced] is on track 0:10. -map option is used to extract it.

ffmpeg -stats -v error -i <your_mkv_file> -map <track(here is 0:10)> <output_file(eng.srt)>

In the same way you can extract JPN subtitles.

ffmpeg -stats -v error -i "xxx.mkv" -map 0:12 "xxx jpn.srt"

Then use this project to merge them.

./srt-merge.js "xxx eng.srt" "xxx jpn.srt" top-bottom -o "xxx merged.srt"

Now, combine these processes into one script.

// Powershell
Get-ChildItem ./ *.mkv | ForEach-Object {
    $srt1 = $_.BaseName + ' eng.srt'
    $srt2 = $_.BaseName + ' jpn.srt'
    ffmpeg -stats -v error -i $_.Name -map 0:10 $srt1
    ffmpeg -stats -v error -i $_.Name -map 0:12 $srt2
    $srt3 = $_.BaseName + ' eng_jpn.srt'
    node /path/to/srt-merge.js $srt1 $srt2 top-bottom -o $srt3
}
Get-ChildItem ./ '* eng.srt' | Remove-Item
Get-ChildItem ./ '* jpn.srt' | Remove-Item

Shift and rename subtitles

This example is for Linux.

Suppose now you have following subtitle files and videos in one folder.

  1. xx01xx.mkv, xx02xx.mkv, xx03xx.mkv
  2. yy01yy_en.srt, yy01yy_jp.srt
  3. yy02yy_en.srt, yy02yy_jp.srt
  4. yy03yy_en.srt, yy03yy_jp.srt

You want to shift these srt files a few seconds and rename it to match MKV filename.

First, You can use Debian package 'subtitleeditor' - it's a GUI subtitle editor - to check how many seconds to shift.

About

Node.js. Merge two srt into one srt, with "top-bottom", "time-shift", "finding nearest" and a few more options.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published