SubSyncForPlex + Home Assistant - Sync Plex Subtitles and Refresh Playback
Learn how I solved the subtitle syncing problem in Plex by building SubSyncForPlex and integrating it with Home Assistant for seamless syncing, notifications, and automatic playback refresh.
One of the small but frustrating problems in my Plex setup used to be subtitle syncing.
I use Bazarr to automatically download subtitles whenever I add new items to my Plex collection.
While Bazarr works great for downloading, the subtitle sync plugin gave me mixed results, sometimes it would sync properly,
but other times it would delete parts of the subtitle file or just make things worse.
Plex has since added automatic subtitle syncing built into the server, and it has improved the experience a lot.
But it’s still not perfect — sometimes it doesn’t kick in, or the timing can still feel just a little bit off.
And usually, it’s my wife who notices first. We’ll be halfway into a movie or show when she points out that the subtitles are a little out of sync — and I have to admit, once she points it out, I can’t unsee it either.
Originally, fixing it meant grabbing my laptop, manually running subsync, and reloading the file.
It got annoying fast.
At first, I tried to automate it with a PowerShell script triggered by HASS.Agent on a Windows VM running in my home lab. That worked…until Windows decided to reboot itself for updates — leaving me to log in and restart everything manually again.
I needed something more reliable — something that could run independently and fit into my Home Assistant setup.
That’s why I built SubSyncForPlex:
A lightweight Python service that automatically syncs subtitles using subsync with a simple webhook — no more grabbing the laptop.
In this post, I’ll walk you through:
- What SubSyncForPlex does
- How I integrated it with Home Assistant to make syncing seamless
- How you can set up a button to sync and refresh your playback
What is SubSyncForPlex?
At a high level, SubSyncForPlex:
- Accepts webhook requests containing a Plex media ID
- Locates the media file and associated subtitle file using the Plex API
- Uses
subsync
to realign subtitle timing - Sends webhook notifications back to Home Assistant (optional)
You can run it standalone or inside a Docker container. I personally run it in Docker for easier management alongside my Home Assistant setup.
Full installation instructions and configuration details are available in the SubSyncForPlex README.
Docker compose example
1
2
3
4
5
6
7
8
9
10
11
12
13
services:
subsyncforplex:
image: 'ghcr.io/chrishansentech/subsyncforplex:latest'
environment:
- HOME_ASSISTANT_WEBHOOK_URL=<optional_webhook_url>
- DEFAULT_SUB_LANG=en #optional defaults to en
- DEFAULT_AUDIO_LANG=en #optional defaults to en
- PLEX_URL=<your_plex_server_url>
- PLEX_TOKEN=<your_plex_token>
volumes:
- '/path/to/media:/media'
ports:
- '8000:8000'
Make sure the /media path inside the container matches the structure of your Plex library as seen by the Plex API. For example, if the Plex API returns a path like
/Plex/Movies/WarGames (1983)/WarGames (1983).mkv
, then your volume mount should be set to:
/path/to/plex/media:/media/Plex
This ensures that the file paths returned by the API can be resolved correctly within the container.
Extending SubSyncForPlex with Home Assistant
While SubSyncForPlex can run on its own, it gets a lot more powerful when you integrate it with Home Assistant. Here’s the flow I built:
- Home Assistant Script:
- Sends a webhook request to SubSyncForPlex containing the current playing media’s ID and Plex media player entity ID.
- Home Assistant Automation:
- Sends a push notification to your phone when syncing starts.
- Sends another notification when it succeeds or fails.
- If successful, it checks if you’re still watching the same media, and refreshes the playback to reload the updated subtitles.
This flow uses the Home Assistant Plex Media Server integration to retrieve the
media_content_id
and refresh playback through Plexmedia_player
entities.
REST Command
Create a rest_command
in your config.yaml
to send the sync request to SubSyncForPlex like this:
1
2
3
4
5
6
7
8
9
10
11
rest_command:
plex_subsync_sync:
url: "http://YOUR_SUBSYNCFORPLEX_SERVER:8000/subsync"
method: POST
headers:
Content-Type: "application/json"
payload: |
{
"media_id": {{ media_id }},
"entity_id": "{{ entity_id }}"
}
Replace YOUR_SUBSYNCFORPLEX_SERVER
with the actual IP or hostname where you’re running SubSyncForPlex.
If you want to specify the language for the audio and subtitle files, you can update your
rest_command
to include"audio_lang": "LANGUAGE_CODE"
and"sub_lang": "LANGUAGE_CODE"
in the payload. You can mix and match languages, as SubSync supports translations.
Script to Trigger SubSyncForPlex
This script grabs the media_content_id
from a Plex integration media_player
entity, and sends it to the SubSyncForPlex webhook.
1
2
3
4
5
6
7
8
9
10
11
12
alias: "Sync Plex Subtitles"
fields:
media_player:
description: "Plex media player entity"
example: "media_player.plex_living_room_tv"
sequence:
- variables:
media_id: "{{ state_attr(media_player, 'media_content_id') }}"
- service: rest_command.plex_subsync_sync
data:
media_id: "{{ media_id }}"
entity_id: "{{ media_player }}"
Example button configuration to call script:
1
2
3
4
5
6
7
8
9
10
11
- type: button
show_icon: true
show_name: true
icon: mdi:subtitles
entity: script.sync_plex_subtitles
tap_action:
action: perform-action
perform_action: script.sync_plex_subtitles
target: {}
data:
media_player: media_player.plex_living_room_tv
Automations for Notifications and Playback Refresh
Here’s an automation that:
- Sends a notification when the sync starts
- Sends another notification when it succeeds or fails
- If successful and you’re still watching the same item, it restarts playback (to reload the updated subtitles).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
alias: "Handle SubSyncForPlex Status"
triggers:
- trigger: webhook
webhook_id: SubSyncForPlex_status
local_only: true
allowed_methods:
- POST
condition: []
actions:
- variables:
stage: "{{ trigger.json.stage }}"
message: "{{ trigger.json.message }}"
media_id: "{{ trigger.json.media_id }}"
entity_id: "{{ trigger.json.entity_id }}"
- choose:
- conditions:
- condition: template
value_template: "{{ stage == 'sync-started' }}"
sequence:
- action: notify.mobile_your_device
data:
title: Subtitle Sync
message: "{{ message }}"
- conditions:
- condition: template
value_template: "{{ stage == 'sync-success' }}"
sequence:
- action: notify.mobile_your_device
data:
title: Subtitle Sync
message: "{{ message }}"
- delay: 2
- condition: template
value_template: >-
{{ state_attr(entity_id, 'media_content_id') == media_id }}
- action: media_player.play_media
target:
entity_id: "{{ entity_id }}"
data:
media_content_id: "{{ media_id }}"
media_content_type: video
- conditions:
- condition: template
value_template: "{{ stage == 'sync-failed' }}"
sequence:
- action: notify.mobile_your_device
data:
title: Subtitle Sync Failed
message: "{{ message }}"
You’ll need to configure your Home Assistant webhook
trigger to listen for webhook payloads from
SubSyncForPlex (webhook_id: SubSyncForPlex_status
) and set up a webhook URL in the SubSyncForPlex config
(HOME_ASSISTANT_WEBHOOK_URL
).
Example:
http://homeassistant.local:8123/api/webhook/SubSyncForPlex_status
How it Works Together
- Start sync manually from a dashboard button using the script.
- Get notified immediately when the sync begins.
- Receive success/failure notifications as soon as it finishes.
- Automatically refresh playback after syncing if you’re still watching the same media on the same Plex client
This has made subtitle syncing basically effortless at my house — and no more resyncing subtitles manually using my laptop on the couch.
Final Thoughts
If you always have subtitles on like we do, SubSyncForPlex with Home Assistant makes subtitle syncing easy, fast, and reliable.
It’s a simple project but has a big impact on the everyday experience of using Plex.
You can find the code and contribute to the project here:
ChrisHansenTech/SubSyncForPlex on GitHub
If you have any suggestions, issues, or improvements, feel free to reach out or open a PR.
Happy syncing!