Local Deployment

Requirements

Python versions: Python Versions

Installation

  1. Install the correct version of PyTorch by following the official instructions: https://pytorch.org/get-started/locally

  2. Install DuoSubs via pip:

    pip install duosubs
    

Basic Usage

Let’s say you have two subtitle files, from the same cut and all their timestamps overlap (see Merging Modes for other subtitle file types) — in any supported format like SRT, VTT, MPL2, TTML, ASS, SSA — for example:

  • primary_sub.srt

  • secondary_sub.srt

And you want to merge them using the timestamps from primary_sub.srt.

Then, you can do it by:

— whichever suits your workflow. Both methods can be run from the command line or via Python code.

Launching Web UI

duosubs launch-webui
from duosubs import create_duosubs_gr_blocks

# Build the Web UI layout (Gradio Blocks)
webui = create_duosubs_gr_blocks()

# These commands work just like launching a regular Gradio app
webui.queue(default_concurrency_limit=None) # Allow unlimited concurrent requests
webui.launch(inbrowser=True)                # Start the Web UI and open it in a browser tab

This will start a local server and display a URL (e.g., http://127.0.0.1:7860), and the Web UI will be started in a new browser tab.

Tip

You can also launch the server on a different host address (e.g. 0.0.0.0) and port (e.g 8000):

duosubs launch-webui --host 0.0.0.0 --port 8000
from duosubs import create_duosubs_gr_blocks

webui = create_duosubs_gr_blocks()

webui.queue(default_concurrency_limit=None)
webui.launch(
    server_name = "0.0.0.0",    # use different address
    server_port = 8000,         # use different port number
    inbrowser=True
)

Warning

  • The Web UI caches files during processing, and clears files older than 4 hours every 1 hour. Cached data may remain if the server stops unexpectedly, and you may need to delete them manually.

  • Sometimes, older model may fail to be released after switching or closing sessions. If you run out of RAM or VRAM, simply restart the script.

Merging Subtitles Directly

duosubs merge -p primary_sub.srt -s secondary_sub.srt
from duosubs import MergeArgs, run_merge_pipeline

# Store all arguments
args = MergeArgs(
    primary="primary_sub.srt",
    secondary="secondary_sub.srt"
)

# Load, merge, and save subtitles.
run_merge_pipeline(args, print)

Default Options and Outputs

This tool uses LaBSE as its default Sentence Transformer model and runs on GPU or MPS (Apple) if available — otherwise it falls back to CPU.

Tip

You can experiment with different models, by choosing one from 🤗 Hugging Face or leaderboard.

For example, if the model chosen is Qwen/Qwen3-Embedding-0.6B, you can run the followings instead:

duosubs merge -p primary_sub.srt -s secondary_sub.srt --model Qwen/Qwen3-Embedding-0.6B
from duosubs import MergeArgs, run_merge_pipeline

# Store all arguments
args = MergeArgs(
    primary="primary_sub.srt",
    secondary="secondary_sub.srt",
    model="Qwen/Qwen3-Embedding-0.6B"
)

# Load, merge, and save subtitles.
run_merge_pipeline(args, print)
In ConfigurationsModel & DeviceSentence Transformer Model, replace sentence-transformers/LaBSE with Qwen/Qwen3-Embedding-0.6B.

Warning

  • Some models may require significant RAM or GPU (VRAM) to run and might not be compatible with all devices — especially larger models.

  • Please ensure the selected model supports your desired language for reliable results.

After merging, you’ll get primary_sub.zip in the Output Zip section (Web UI) or in the same directory as primary_sub.srt (CLI/Python), with the following structure:

primary_sub.zip
├── primary_sub_combined.ass   # Merged subtitles
├── primary_sub_primary.ass    # Original primary subtitles
└── primary_sub_secondary.ass  # Time-shifted secondary subtitles

All these subtitles are saved in .ass format by default.

In the merged file (primary_sub_combined.ass), the displayed subtitles will have primary subtitles placed above the secondary subtitles, and line breaks are removed for cleaner formatting.

You can customize all these options in the configurations section of the Web UI, CLI or Python API.

Merging Modes

This tool supports three merging modes:

Mode

Same cut

Timestamps overlap

synced

✓ (all timestamps)

mixed

✗ (some or all may not overlap)

cuts

✗ (primary being longer version)

Here are some of the simple guidelines to choose the appropriate mode:

  • If both subtitle files are timestamp-synced, use synced for the cleanest result.

  • If timestamps drift or only partially overlap, use mixed.

  • If subtitles come from different editions of the video, with primary subtitles being the extended or longer version, use cuts.

Tip

For mixed and cuts modes, try to use subtitle files without scene annotations if possible, as they may reduce alignment quality.

To merge with a specific mode (e.g. cuts), run:

duosubs merge -p primary_sub.srt -s secondary_sub.srt --mode cuts
from duosubs import MergeArgs, MergingMode, run_merge_pipeline

# Store all arguments
args = MergeArgs(
    primary="primary_sub.srt",
    secondary="secondary_sub.srt",
    merging_mode=MergingMode.CUTS   # Modes available: MergingMode.SYNCED, MergingMode.MIXED, MergingMode.CUTS
)

# Load, merge, and save subtitles.
run_merge_pipeline(args, print)
In ConfigurationsAlignment BehaviorMerging Mode, choose Cuts.