Queue-based subtitle synchronization service for Bazarr workflows, powered by sc0ty/subsync.
- Watches a queue directory for JSON jobs produced by Bazarr post-processing.
- Runs
subsyncfor eachvideoandsubtitlepair. - Validates required job fields before processing.
- Optionally refreshes Plex sections after successful synchronization.
- Keeps logs and execution artifacts for operational diagnostics.
bazarr-postprocess.sh- Bazarr hook that writes queue jobs.subsync-monitor.sh- queue watcher and job dispatcher.subsync-wrapper.sh-subsyncexecution and result handling.docker-compose.yml- service runtime mounts and environment.Dockerfile- container image with runtime dependencies.
- Clone this repository.
- Copy environment template:
cp .env.example .env- Edit
.envand set at least:MEDIA_HOST_PATH(absolute host path to your media)- optional Plex variables if you use that integration
- Start service:
docker compose up -d --build- Verify container is running:
docker compose ps
docker compose logs -f subsyncUse this command in Bazarr custom post-processing:
/config/scripts/bazarr-postprocess.sh {{episode}} {{subtitles}} {{subtitles_language_code3}} {{episode_language_code3}}
The script is included in this repository as bazarr-postprocess.sh.
For a Bazarr container/user:
- Copy it into Bazarr scripts folder (example):
cp bazarr-postprocess.sh /config/scripts/bazarr-postprocess.sh
chmod +x /config/scripts/bazarr-postprocess.sh-
Make sure Bazarr writes queue files to a path shared with
subsync.- In Bazarr environment, set
SUBSYNC_QUEUE_DIR(example:/config/scripts/subsync-queue). - In
subsyncservice, mount the same host directory to/queue.
- In Bazarr environment, set
-
Make sure media paths from Bazarr (
{{episode}},{{subtitles}}) exist inside thesubsynccontainer too.- This is why
MEDIA_HOST_PATHandMEDIA_CONTAINER_PATHmust reflect your real mapping.
- This is why
-
bazarr-postprocess.shexists in Bazarr scripts directory and is executable. - Bazarr post-processing command is exactly:
/config/scripts/bazarr-postprocess.sh {{episode}} {{subtitles}} {{subtitles_language_code3}} {{episode_language_code3}}
-
SUBSYNC_QUEUE_DIRpoints to a directory shared with thesubsynccontainer. - The shared queue directory is mounted to
/queueinsubsync. - Media paths from Bazarr are valid inside
subsync(same path mapping semantics). - A test subtitle download creates a
job-*.jsonfile and it disappears after processing. -
docker compose logs -f subsyncshows a successful run (OK SubSync completed successfully).
Each job is a JSON file in /queue with at least:
{
"video": "/media/shows/Show/Season 01/Episode.mkv",
"subtitle": "/media/shows/Show/Season 01/Episode.pl.srt",
"subtitle_lang": "pol",
"video_lang": "eng"
}Required keys: video, subtitle.
See .env.example for all variables.
Common knobs:
SUBSYNC_EFFORTSUBSYNC_MAX_WINDOWSUBSYNC_MIN_CORRELATIONSUBSYNC_LOG_LEVEL
Optional integrations:
- Plex:
PLEX_URL,PLEX_TOKEN,PLEX_SECTION_SHOWS,PLEX_SECTION_MOVIES
- Check logs:
docker compose logs -f subsync- inspect
/logs/subsync-exec.loginside mounted logs directory
- Your media mapping is inconsistent.
- Verify that path from Bazarr exists inside
subsynccontainer.
- Check queue mount:
- host queue path from
.envmust be mounted to/queue
- host queue path from
- Confirm queue files end with
.json.
- Missing or invalid
PLEX_URLorPLEX_TOKEN. - Sync itself still succeeds; Plex refresh is non-blocking.
- Treat the queue directory as a trusted input boundary.
- Only Bazarr (or trusted automation) should be able to write
*.jsonfiles to/queue. - Do not commit
.envfiles or share logs that include internal hostnames/URLs.
Run local verification before publishing:
bash -n subsync-monitor.sh
bash -n subsync-wrapper.sh
bash -n bazarr-postprocess.sh
docker compose config
docker build -t bazarr-subsync-bridge .bazarr-postprocess.shsubsync-monitor.shsubsync-wrapper.shdocker-compose.ymlDockerfile.env.example
- commit subject:
type/scope: action object - PR sections:
## Summary,## Verification(plus## Risk and rollback/## Noteswhen relevant)
SECURITY.mdCONTRIBUTING.mdCODE_OF_CONDUCT.mdLICENSE