Update README.md
Browse files
README.md
CHANGED
|
@@ -1,321 +1,10 @@
|
|
| 1 |
-
# Subgen
|
| 2 |
-
|
| 3 |
-
[](https://www.paypal.com/donate/?hosted_button_id=SU4QQP6LH5PF6)
|
| 4 |
-
<img src="https://raw.githubusercontent.com/McCloudS/subgen/main/icon.png" width="200">
|
| 5 |
-
|
| 6 |
-
<details>
|
| 7 |
-
<summary><strong>Updates:</strong></summary>
|
| 8 |
-
|
| 9 |
-
7 Jun 2026: Fixed a bug where files containing only a **forced** embedded subtitle track were incorrectly treated as having full subtitle coverage and skipped. Forced tracks cover only a small fraction of dialogue (typically foreign-language inserts) and should not count as full coverage. Added `IGNORE_FORCED_SUBTITLES` (default `True`) to control this behaviour.
|
| 10 |
-
|
| 11 |
-
11 Apr 2026: Fixed subtitle timing on files with audio stream offsets (common in Amazon WEB-DL). Whisper ignores silence padding, causing subtitles to be early by the offset amount. Subgen now detects this via ffprobe and compensates automatically when the source video file is accessible. See [Audio Start-Time Offset Fix](#-audio-start-time-offset-fix) for details.
|
| 12 |
-
|
| 13 |
-
27 Mar 2026: Potentially added ROCm support for AMD GPU/APUs. I don't have anything to test it, so a fair chance it doesn't work at all. I'm unsure if it will work with AMD APUs. Image is: `mccloud/subgen:amd`. It's pretty large right now at ~10gb. In theory, it should see your AMD card the same way it sees any other cuda device. Some light research shows ROCm only 'officially' supports higher end consumer cards and datacenter cards. `HSA_OVERRIDE_GFX_VERSION` can be set to 'trick' your old cards (and maybe APUs) to work, but you'll have to do your own research/googling.
|
| 14 |
-
|
| 15 |
-
17 Mar 2026: Added `WEBHOOK_URL_COMPLETED`. When a task finishes, Subgen will send a POST request with a JSON structure.
|
| 16 |
-
|
| 17 |
-
4 Mar 2026: Reformmated the readme and spend an hour with Gemini trying to format it and clean it up and it essentially only gave me icons for headers.
|
| 18 |
-
|
| 19 |
-
Feb 2026: Contributor helped cut the GPU container size in half. Added `ASR_TIMEOUT` as environment variable to timeout ASR endpoint transcriptions after X seconds.
|
| 20 |
-
|
| 21 |
-
31 Jan 2026: Added the ability to run the container 'rootless', accepts `PUID` and `PGID` as environment variables and _should_ take `user` at a container level (Podman), let me know!.
|
| 22 |
-
|
| 23 |
-
13 Jan 2026: Probably fixed the runaway memory problems for CPU only. Added `MODEL_CLEANUP_DELAY` which will wait X seconds before purging the model to clear up (V)RAM. This mostly helps with Bazarr or when concurrent transcriptions is 1. Rewrote ASR (Bazarr) queuing so it should respect queing and follow concurrent transcriptions. Also fixed the error when too many Bazarr or ASR requests would start to fail.
|
| 24 |
-
|
| 25 |
-
26 Aug 2025: Renamed environment variables to make them slightly easier to understand. Currently maintains backwards compatibility. See https://github.com/McCloudS/subgen/pull/229
|
| 26 |
-
|
| 27 |
-
12 Aug 2025: Added distil-large-v3.5
|
| 28 |
-
|
| 29 |
-
7 Feb 2025: Fixed (V)RAM clearing, added PLEX_QUEUE_SEASON, other extraneous fixes or refactorting.
|
| 30 |
-
|
| 31 |
-
23 Dec 2025: Added PLEX_QUEUE_NEXT_EPISODE and PLEX_QUEUE_SERIES. Will automatically start generating subtitles for the next episode in your series, or queue the whole series.
|
| 32 |
-
|
| 33 |
-
4 Dec 2025: Added more ENV settings: DETECT_LANGUAGE_OFFSET, PREFERRED_AUDIO_LANGUAGES, SKIP_IF_AUDIO_TRACK_IS, ONLY_SKIP_IF_SUBGEN_SUBTITLE, SKIP_UNKNOWN_LANGUAGE, SKIP_IF_LANGUAGE_IS_NOT_SET_BUT_SUBTITLES_EXIST, SHOULD_WHISPER_DETECT_AUDIO_LANGUAGE
|
| 34 |
-
|
| 35 |
-
30 Nov 2024: Signifcant refactoring and handling by Muisje. Added language code class for more robustness and flexibility and ability to separate audio tracks to make sure you get the one you want. New ENV Variables: SUBTITLE_LANGUAGE_NAMING_TYPE, SKIP_IF_AUDIO_TRACK_IS, PREFERRED_AUDIO_LANGUAGE, SKIP_IF_TO_TRANSCRIBE_SUB_ALREADY_EXIST
|
| 36 |
-
There will be some minor hiccups, so please identify them as we work through this major overhaul.
|
| 37 |
-
|
| 38 |
-
22 Nov 2024: Updated to support large-v3-turbo
|
| 39 |
-
|
| 40 |
-
30 Sept 2024: Removed webui
|
| 41 |
-
|
| 42 |
-
5 Sept 2024: Fixed Emby response to a test message/notification. Clarified Emby/Plex/Jellyfin instructions for paths.
|
| 43 |
-
|
| 44 |
-
14 Aug 2024: Cleaned up usage of kwargs across the board a bit. Added ability for /asr to encode or not, so you don't need to worry about what files/formats you upload.
|
| 45 |
-
|
| 46 |
-
3 Aug 2024: Added SUBGEN_KWARGS environment variable which allows you to override the model.transcribe with most options you'd like from whisper, faster-whisper, or stable-ts. This won't be exposed via the webui, it's best to set directly.
|
| 47 |
-
|
| 48 |
-
21 Apr 2024: Fixed queuing with thanks to https://github.com/xhzhu0628 @ https://github.com/McCloudS/subgen/pull/85. Bazarr intentionally doesn't follow `CONCURRENT_TRANSCRIPTIONS` because it needs a time sensitive response.
|
| 49 |
-
|
| 50 |
-
31 Mar 2024: Removed `/subsync` endpoint and general refactoring. Open an issue if you were using it!
|
| 51 |
-
|
| 52 |
-
24 Mar 2024: ~~Added a 'webui' to configure environment variables. You can use this instead of manually editing the script or using Environment Variables in your OS or Docker (if you want). The config will prioritize OS Env Variables, then the .env file, then the defaults. You can access it at `http://subgen:9000/`~~
|
| 53 |
-
|
| 54 |
-
23 Mar 2024: Added `CUSTOM_REGROUP` to try to 'clean up' subtitles a bit.
|
| 55 |
-
|
| 56 |
-
22 Mar 2024: Added LRC capability via see: `LRC_FOR_AUDIO_FILES | True | Will generate LRC (instead of SRT) files for filetypes: '.mp3', '.flac', '.wav', '.alac', '.ape', '.ogg', '.wma', '.m4a', '.m4b', '.aac', '.aiff'`
|
| 57 |
-
|
| 58 |
-
21 Mar 2024: Added a 'wizard' into the launcher that will help standalone users get common Bazarr variables configured. See below in Launcher section. Removed 'Transformers' as an option. While I usually don't like to remove features, I don't think anyone is using this and the results are wildly unpredictable and often cause out of memory errors. Added two new environment variables called `USE_MODEL_PROMPT` and `CUSTOM_MODEL_PROMPT`. If `USE_MODEL_PROMPT` is `True` it will use `CUSTOM_MODEL_PROMPT` if set, otherwise will default to using the pre-configured language pairings. These pre-configurated translations are geared towards fixing some audio that may not have punctionation. We can prompt it to try to force the use of punctuation during transcription.
|
| 59 |
-
|
| 60 |
-
19 Mar 2024: Added a `MONITOR` environment variable. Will 'watch' or 'monitor' your `TRANSCRIBE_FOLDERS` for changes and run on them. Useful if you just want to paste files into a folder and get subtitles.
|
| 61 |
-
|
| 62 |
-
6 Mar 2024: Added a `/subsync` endpoint that can attempt to align/synchronize subtitles to a file. Takes audio_file, subtitle_file, language (2 letter code), and outputs an srt.
|
| 63 |
-
|
| 64 |
-
5 Mar 2024: Cleaned up logging. Added timestamps option (if Debug = True, timestamps will print in logs).
|
| 65 |
-
|
| 66 |
-
4 Mar 2024: Updated Dockerfile CUDA to 12.2.2 (From CTranslate2). Added endpoint `/status` to return Subgen version. Can also use distil models now! See variables below!
|
| 67 |
-
|
| 68 |
-
29 Feb 2024: Changed default port to align with whisper-asr and deconflict other consumers of the previous port.
|
| 69 |
-
|
| 70 |
-
11 Feb 2024: Added a 'launcher.py' file for Docker to prevent huge image downloads. Now set UPDATE to True if you want pull the latest version, otherwise it will default to what was in the image on build. Docker builds will still be auto-built on any commit. If you don't want to use the auto-update function, no action is needed on your part and continue to update docker images as before. Fixed bug where detect-langauge could return an empty result. Reduced useless debug output that was spamming logs and defaulted DEBUG to True. Added APPEND, which will add a transcribed watermark at the end of a subtitle.
|
| 71 |
-
|
| 72 |
-
10 Feb 2024: Added some features from JaiZed's branch such as skipping if SDH subtitles are detected, functions updated to also be able to transcribe audio files, allow individual files to be manually transcribed, and a better implementation of forceLanguage. Added `/batch` endpoint (Thanks JaiZed). Allows you to navigate in a browser to http://subgen_ip:9000/docs and call the batch endpoint which can take a file or a folder to manually transcribe files. Added CLEAR_VRAM_ON_COMPLETE, HF_TRANSFORMERS, HF_BATCH_SIZE. Hugging Face Transformers boast '9x increase', but my limited testing shows it's comparable to faster-whisper or slightly slower. I also have an older 8gb GPU. Simplest way to persist HF Transformer models is to set "HF_HUB_CACHE" and set it to "/subgen/models" for Docker (assuming you have the matching volume).
|
| 73 |
-
|
| 74 |
-
8 Feb 2024: Added FORCE_DETECTED_LANGUAGE_TO to force a wrongly detected language. Fixed asr to actually use the language passed to it.
|
| 75 |
-
|
| 76 |
-
5 Feb 2024: General housekeeping, minor tweaks on the TRANSCRIBE_FOLDERS function.
|
| 77 |
-
|
| 78 |
-
28 Jan 2024: Fixed issue with ffmpeg python module not importing correctly. Removed separate GPU/CPU containers. Also removed the script from installing packages, which should help with odd updates I can't control (from other packages/modules). The image is a couple gigabytes larger, but allows easier maintenance.
|
| 79 |
-
|
| 80 |
-
19 Dec 2023: Added the ability for Plex and Jellyfin to automatically update metadata so the subtitles shows up properly on playback. (See https://github.com/McCloudS/subgen/pull/33 from Rikiar73574)
|
| 81 |
-
|
| 82 |
-
31 Oct 2023: Added Bazarr support via Whipser provider.
|
| 83 |
-
|
| 84 |
-
25 Oct 2023: Added Emby (IE http://192.168.1.111:9000/emby) support and TRANSCRIBE_FOLDERS, which will recurse through the provided folders and generate subtitles. It's geared towards attempting to transcribe existing media without using a webhook.
|
| 85 |
-
|
| 86 |
-
23 Oct 2023: There are now two docker images, ones for CPU (it's smaller): mccloud/subgen:latest, mccloud/subgen:cpu, the other is for cuda/GPU: mccloud/subgen:cuda. I also added Jellyfin support and considerable cleanup in the script. I also renamed the webhooks, so they will require new configuration/updates on your end. Instead of /webhook they are now /plex, /tautulli, and /jellyfin.
|
| 87 |
-
|
| 88 |
-
22 Oct 2023: The script should have backwards compability with previous envirionment settings, but just to be sure, look at the new options below. If you don't want to manually edit your environment variables, just edit the script manually. While I have added GPU support, I haven't tested it yet.
|
| 89 |
-
|
| 90 |
-
19 Oct 2023: And we're back! Uses faster-whisper and stable-ts. Shouldn't break anything from previous settings, but adds a couple new options that aren't documented at this point in time. As of now, this is not a docker image on dockerhub. The potential intent is to move this eventually to a pure python script, primarily to simplify my efforts. Quick and dirty to meet dependencies: pip or `pip3 install flask requests stable-ts faster-whisper`
|
| 91 |
-
|
| 92 |
-
This potentially has the ability to use CUDA/Nvidia GPU's, but I don't have one set up yet. Tesla T4 is in the mail!
|
| 93 |
-
|
| 94 |
-
2 Feb 2023: Added Tautulli webhooks back in. Didn't realize Plex webhooks was PlexPass only. See below for instructions to add it back in.
|
| 95 |
-
|
| 96 |
-
31 Jan 2023 : Rewrote the script substantially to remove Tautulli and fix some variable handling. For some reason my implementation requires the container to be in host mode. My Plex was giving "401 Unauthorized" when attempt to query from docker subnets during API calls. (**Fixed now, it can be in bridge**)
|
| 97 |
-
</details>
|
| 98 |
-
|
| 99 |
---
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
---
|
| 110 |
-
|
| 111 |
-
## ⚡ Quick Start: Bazarr (The Bare Minimum)
|
| 112 |
-
If you just want to plug Subgen into Bazarr and get going, here is the absolute minimum you need to configure in your Subgen Docker container. **No path mapping or media mounts are needed!**
|
| 113 |
-
|
| 114 |
-
**1. Set your Environment Variables in Subgen:**
|
| 115 |
-
* `TRANSCRIBE_DEVICE`: Set to `cuda` if you have an Nvidia GPU (highly recommended for speed), otherwise leave as `cpu`.
|
| 116 |
-
* `WHISPER_MODEL`: Default is `medium`. Try `large-v3-turbo` if you have a GPU with 8GB+ VRAM for faster transcription. **Note:** `large-v3-turbo` only supports transcription — if you need translation (e.g. `TRANSCRIBE_OR_TRANSLATE=translate`), use `large-v3` instead.
|
| 117 |
-
* `CONCURRENT_TRANSCRIPTIONS`: Default is `2`. Lower to `1` if you are running out of RAM/VRAM.
|
| 118 |
-
|
| 119 |
-
**2. Configure Bazarr:**
|
| 120 |
-
* In Bazarr, go to **Settings > Whisper Provider**.
|
| 121 |
-
* Select **Whisper** as the provider.
|
| 122 |
-
* Set the **Docker Endpoint** to your Subgen IP and port: `http://<your-ip>:9000` *(Note: Do not use `127.0.0.1` if Bazarr is also in a Docker container).*
|
| 123 |
-
* Save! Subgen will now act as an invisible, self-hosted API for Bazarr's transcription requests.
|
| 124 |
-
|
| 125 |
-
**3. Disable Auto-Sync for Subgen subtitles (important):**
|
| 126 |
-
Subgen already produces accurately timed subtitles. If you have Bazarr's **Automatic Subtitles Audio Synchronization** enabled, you must exclude `whisperai` from it — otherwise Bazarr will run ffsubsync on top of already-synced subtitles and degrade their quality.
|
| 127 |
-
* In Bazarr, go to **Settings > Subtitles > Audio Synchronization**.
|
| 128 |
-
* Under **"Do not sync subtitles downloaded from those providers"**, add **`whisperai`**.
|
| 129 |
-
|
| 130 |
-
---
|
| 131 |
-
|
| 132 |
-
## 🔧 Audio Start-Time Offset Fix
|
| 133 |
-
|
| 134 |
-
Some media containers — particularly Amazon WEB-DL files — have an audio stream that starts later than the video stream (e.g., audio `start_time` of ~4 seconds). When Bazarr extracts audio from these files, it compensates by prepending silence via ffmpeg's `adelay` filter. However, Whisper's speech recognition completely ignores this digital silence, producing timestamps that are early by the offset amount (e.g., every subtitle appears ~4 seconds too early).
|
| 135 |
-
|
| 136 |
-
Subgen now automatically detects and compensates for this. When the source video file is accessible, it uses `ffprobe` to read the audio stream's `start_time` metadata, then shifts all Whisper timestamps forward by that amount after transcription.
|
| 137 |
-
|
| 138 |
-
**This fix is fully backwards compatible.** If the video file is not accessible, or has no audio offset (i.e. `start_time` is 0), behaviour is completely unchanged.
|
| 139 |
-
|
| 140 |
-
### How to enable it (Bazarr)
|
| 141 |
-
|
| 142 |
-
1. **Mount your media into the Subgen container** with the same paths that Bazarr sees. For example, if Bazarr sees TV shows at `/tv`, add a volume mount so Subgen also sees `/tv`:
|
| 143 |
-
```yaml
|
| 144 |
-
volumes:
|
| 145 |
-
- /path/to/your/tv:/tv
|
| 146 |
-
- /path/to/your/movies:/movies
|
| 147 |
-
```
|
| 148 |
-
|
| 149 |
-
2. **Enable "Pass Video Name" in Bazarr.** Go to **Settings > Whisper Provider** and check the **Pass Video Name** option. This tells Bazarr to send the video file path alongside the audio, allowing Subgen to look up the source file and detect any audio offset.
|
| 150 |
-
|
| 151 |
-
That's it. No new environment variables are required. Files without an audio offset are unaffected.
|
| 152 |
-
|
| 153 |
-
---
|
| 154 |
-
|
| 155 |
-
## 🛠 Installation & Setup
|
| 156 |
-
|
| 157 |
-
### 1. Docker (Recommended)
|
| 158 |
-
The easiest way to run Subgen is via Docker. We maintain an image on Docker Hub (`mccloud/subgen`).
|
| 159 |
-
* `mccloud/subgen:latest` (Supports both CPU and GPU/CUDA)
|
| 160 |
-
* `mccloud/subgen:cpu` (Smaller image, CPU only)
|
| 161 |
-
|
| 162 |
-
**Crucial Note on Volume Mapping:** If you are using Plex/Emby/Jellyfin/Tautulli webhooks, **Subgen must see your media paths exactly identically to how your media server sees them.** For example, if Plex uses `/Share/media/TV:/tv`, Subgen needs that exact same volume mount. *(Note: This does not apply to Bazarr, which sends audio over HTTP).*
|
| 163 |
-
|
| 164 |
-
### 2. Standalone (Without Docker)
|
| 165 |
-
1. Install Python 3.9–3.11 and `ffmpeg`.
|
| 166 |
-
2. Ensure you have the proper NVIDIA drivers/CUDA toolkit installed (if using GPU).
|
| 167 |
-
3. Download `launcher.py` from this repository and run:
|
| 168 |
-
> `python3 launcher.py -u -i -s`
|
| 169 |
-
|
| 170 |
-
*(Launcher includes a wizard to help standalone users easily configure common variables).*
|
| 171 |
-
|
| 172 |
-
### 3. Unraid
|
| 173 |
-
While Unraid doesn't have an app or template for quick install, with minor manual work, you can easily install it. See [this discussion thread](https://github.com/McCloudS/subgen/discussions/137) for pictures and steps.
|
| 174 |
-
|
| 175 |
-
---
|
| 176 |
-
|
| 177 |
-
## 🔌 Integrations & Webhooks Setup
|
| 178 |
-
|
| 179 |
-
Choose your preferred integration below. **Do not enable multiple webhooks for the same media events** (e.g., don't use both Tautulli and Plex webhooks for "playback start"), or you will generate duplicate subtitles!
|
| 180 |
-
|
| 181 |
-
### 🟠 Plex
|
| 182 |
-
Requires Plex Pass. Plex and Subgen must have identical path configurations (or use Path Mapping).
|
| 183 |
-
1. In Plex, go to **Settings > Webhooks**.
|
| 184 |
-
2. Add a new webhook pointing to your Subgen instance: `http://<your-ip>:9000/plex`
|
| 185 |
-
3. You will also need to generate a [Plex Token](https://support.plex.tv/articles/204059436-finding-an-authentication-token-x-plex-token/).
|
| 186 |
-
4. **Relevant Variables:** `PLEX_SERVER`, `PLEX_TOKEN`.
|
| 187 |
-
|
| 188 |
-
### 🔵 Jellyfin
|
| 189 |
-
Jellyfin and Subgen must have identical path configurations (or use Path Mapping).
|
| 190 |
-
1. Install the **Webhooks** plugin in Jellyfin.
|
| 191 |
-
2. Click **Add Generic Destination**.
|
| 192 |
-
3. Name it whatever you like, and set the Webhook URL to: `http://<your-ip>:9000/jellyfin`
|
| 193 |
-
4. Check **Item Added**, **Playback Start**, and **Send All Properties**.
|
| 194 |
-
5. Click **Add Request Header**. Set Key: `Content-Type` and Value: `application/json`.
|
| 195 |
-
6. **Relevant Variables:** `JELLYFIN_SERVER`, `JELLYFIN_TOKEN`.
|
| 196 |
-
|
| 197 |
-
### 🟢 Emby
|
| 198 |
-
Emby and Subgen must have identical path configurations (or use Path Mapping). Emby responses contain full info, so no API tokens are required!
|
| 199 |
-
1. In Emby, create a webhook pointing to: `http://<your-ip>:9000/emby`
|
| 200 |
-
2. Set **Request content type** to `multipart/form-data`.
|
| 201 |
-
3. Configure your desired events (Usually `New Media Added`, `Start`, and `Unpause`).
|
| 202 |
-
|
| 203 |
-
### 🟣 Tautulli
|
| 204 |
-
Tautulli and Subgen must have identical path configurations (or use Path Mapping).
|
| 205 |
-
Create two separate Webhooks in Tautulli pointing to `http://<your-ip>:9000/tautulli` using the **POST** method.
|
| 206 |
-
|
| 207 |
-
**Webhook 1: Playback Start**
|
| 208 |
-
* **Trigger:** Playback Start
|
| 209 |
-
* **JSON Header:** `{"source": "Tautulli"}`
|
| 210 |
-
* **Data (JSON):**
|
| 211 |
-
> `{"event": "played", "file": "{file}", "filename": "{filename}", "mediatype": "{media_type}"}`
|
| 212 |
-
|
| 213 |
-
**Webhook 2: Recently Added**
|
| 214 |
-
* **Trigger:** Recently Added
|
| 215 |
-
* **JSON Header:** `{"source": "Tautulli"}`
|
| 216 |
-
* **Data (JSON):**
|
| 217 |
-
> `{"event": "added", "file": "{file}", "filename": "{filename}", "mediatype": "{media_type}"}`
|
| 218 |
-
|
| 219 |
-
---
|
| 220 |
-
|
| 221 |
-
## ⚙️ Configuration (Environment Variables)
|
| 222 |
-
|
| 223 |
-
*Note: Subgen recently standardized environment variables (e.g., `PLEX_TOKEN`). Legacy names (e.g., `PLEXTOKEN`) are still fully supported for backwards compatibility!*
|
| 224 |
-
|
| 225 |
-
### 🧠 Core Whisper & AI Settings
|
| 226 |
-
| Variable | Default | Description |
|
| 227 |
-
|---|---|---|
|
| 228 |
-
| `TRANSCRIBE_DEVICE` | `cpu` | Device to transcribe on: `cpu`, `gpu`, or `cuda`. |
|
| 229 |
-
| `WHISPER_MODEL` | `medium` | Model to use: `tiny`, `base`, `small`, `medium`, `large-v3`, `distil-large-v3`, `large-v3-turbo`, etc. **`large-v3-turbo` does not support translation** (fine-tuned on transcription only) — use `large-v3` if `TRANSCRIBE_OR_TRANSLATE=translate`. |
|
| 230 |
-
| `CONCURRENT_TRANSCRIPTIONS` | `2` | Number of files to process in parallel. |
|
| 231 |
-
| `WHISPER_THREADS` | `4` | Number of CPU threads to use during computation. |
|
| 232 |
-
| `COMPUTE_TYPE` | `auto` | Precision quantization mapping (e.g., `float16`, `int8`). See [CTranslate2 docs](https://github.com/OpenNMT/CTranslate2/blob/master/docs/quantization.md). |
|
| 233 |
-
| `CLEAR_VRAM_ON_COMPLETE` | `True` | Do garbage collection and clear the model from VRAM when the queue is empty. |
|
| 234 |
-
| `MODEL_CLEANUP_DELAY` | `30` | Seconds to wait before clearing the Whisper model from memory. |
|
| 235 |
-
| `ASR_TIMEOUT` | `18000` | Seconds to wait before timing out a transcription request (default 5 hours). |
|
| 236 |
-
| `SUBGEN_KWARGS` | `{}` | JSON dict to pass pure kwargs to Whisper (e.g. `{'vad': True}`). For advanced users. |
|
| 237 |
-
|
| 238 |
-
### ⚡ Processing Triggers & Queuing
|
| 239 |
-
*(Not relevant for Bazarr users)*
|
| 240 |
-
| Variable | Default | Description |
|
| 241 |
-
|---|---|---|
|
| 242 |
-
| `PROCESS_ADDED_MEDIA` | `True` | Generate subs for newly added media (when triggered by webhook). |
|
| 243 |
-
| `PROCESS_MEDIA_ON_PLAY` | `True` | Generate subs for media when it is played (when triggered by webhook). |
|
| 244 |
-
| `TRANSCRIBE_FOLDERS` | `''` | Pipe-separated list (e.g., `/tv|/movies`) to recurse through and queue existing media. |
|
| 245 |
-
| `MONITOR` | `False` | Actively watches `TRANSCRIBE_FOLDERS` in real-time for newly pasted files. |
|
| 246 |
-
| `PLEX_QUEUE_NEXT_EPISODE` | `False` | Auto-queues the *next* Plex episode when Subgen is triggered. |
|
| 247 |
-
| `PLEX_QUEUE_SEASON` | `False` | Auto-queues the *entire remaining season* when Subgen is triggered. |
|
| 248 |
-
| `PLEX_QUEUE_SERIES` | `False` | Auto-queues the *entire remaining series* when Subgen is triggered. |
|
| 249 |
-
| `WEBHOOK_URL_COMPLETED` | `''` | Sends a POST to the `WEBHOOK_URL_COMPLETED` URL with a JSON containing: <br><code>{<br> "event": "transcribed",<br> "file": "/absolute/path/to/video.mkv",<br> "subtitle": "/absolute/path/to/video.en.srt",<br> "language": "en"<br>}</code><br>It will not fire on skips, `/asr` or `/detect-language`. |
|
| 250 |
-
|
| 251 |
-
### ⏭️ Skip Logic & Audio Targeting
|
| 252 |
-
*Prevent Subgen from wasting time on files that don't need subtitles.*
|
| 253 |
-
| Variable | Default | Description |
|
| 254 |
-
|---|---|---|
|
| 255 |
-
| `SKIP_IF_TARGET_SUBTITLES_EXIST` | `True` | Skips if an auto-generated subtitle in your desired language already exists. |
|
| 256 |
-
| `SKIP_IF_EXTERNAL_SUBTITLES_EXIST`| `False` | Skips if an external subtitle matching `SUBTITLE_LANGUAGE_NAME` is found. |
|
| 257 |
-
| `SKIP_IF_INTERNAL_SUBTITLES_LANGUAGE`| `eng` | Skips if the file contains an embedded sub with this 3-letter code. |
|
| 258 |
-
| `SKIP_SUBTITLE_LANGUAGES` | `''` | Pipe-separated list (e.g., `eng\|spa`). Skips if the file *has audio* in these languages. |
|
| 259 |
-
| `SKIP_IF_AUDIO_LANGUAGES` | `''` | Pipe-separated list (ISO 639-2). Skips generation if the file has audio tracks in these languages. |
|
| 260 |
-
| `PREFERRED_AUDIO_LANGUAGES` | `eng` | Pipe-separated list. If multiple audio tracks exist, prefer transcribing this one. |
|
| 261 |
-
| `LIMIT_TO_PREFERRED_AUDIO_LANGUAGE`| `False` | If True, skips files that do not have any audio tracks matching your preferred list. |
|
| 262 |
-
| `FORCE_DETECTED_LANGUAGE_TO` | `''` | Force model to this 2-letter language code if it keeps incorrectly detecting audio. |
|
| 263 |
-
| `DETECT_LANGUAGE_LENGTH` | `30` | Number of seconds to analyze audio to determine the language. |
|
| 264 |
-
| `DETECT_LANGUAGE_OFFSET` | `0` | Number of seconds to skip forward before detecting language (good for avoiding theme songs). |
|
| 265 |
-
| `SHOULD_WHISPER_DETECT_AUDIO_LANGUAGE` | `False` | Should Whisper detect language if there is no audio language tagged in the media file. |
|
| 266 |
-
| `SKIP_UNKNOWN_LANGUAGE` | `False` | Skip processing if Whisper cannot detect the audio language. |
|
| 267 |
-
| `SKIP_ONLY_SUBGEN_SUBTITLES` | `False` | Skips generation only if the file has "subgen" somewhere in the existing subtitle filename. |
|
| 268 |
-
| `SKIP_IF_NO_LANGUAGE_BUT_SUBTITLES_EXIST`| `False` | Skips generation if file doesn't have an audio stream marked with a language, but subtitles exist. |
|
| 269 |
-
| `IGNORE_FORCED_SUBTITLES` | `True` | When `True`, forced embedded subtitle tracks are excluded from all skip-coverage checks. A file whose only matching subtitle tracks are forced will be treated as having no coverage and transcribed normally. Set to `False` to count forced tracks as full coverage (old behaviour). |
|
| 270 |
-
|
| 271 |
-
### 📝 Subtitle Formatting & Preferences
|
| 272 |
-
| Variable | Default | Description |
|
| 273 |
-
|---|---|---|
|
| 274 |
-
| `TRANSCRIBE_OR_TRANSLATE` | `transcribe` | `transcribe` (matches input language) or `translate` (outputs English). |
|
| 275 |
-
| `SUBTITLE_LANGUAGE_NAME` | `aa` | Subtitle file name language code (e.g. `en`). Defaults to `aa` so it floats to the top of Plex's list. |
|
| 276 |
-
| `SUBTITLE_LANGUAGE_NAMING_TYPE`| `ISO_639_2_B` | Format to name files (`ISO_639_1`, `ISO_639_2_T`, `NAME`, `NATIVE`). |
|
| 277 |
-
| `LRC_FOR_AUDIO_FILES` | `True` | Generates `.lrc` instead of `.srt` if processing pure audio files (e.g., mp3, flac). |
|
| 278 |
-
| `WORD_LEVEL_HIGHLIGHT` | `False` | Highlights words dynamically as they are spoken in the subtitle. |
|
| 279 |
-
| `APPEND` | `False` | Appends a "Transcribed by whisperAI..." watermark at the very end of the `.srt`. |
|
| 280 |
-
| `SHOW_IN_SUBNAME_SUBGEN` | `True` | Adds `.subgen` to the output file name. |
|
| 281 |
-
| `SHOW_IN_SUBNAME_MODEL` | `True` | Adds the model used (e.g., `.medium`) to the output file name. |
|
| 282 |
-
| `CUSTOM_REGROUP` | `cm_sl=84_sl=42++++++1` | Stable-TS grouping. Try to 'clean up' subtitles a bit. Set to `default` to use base Stable-TS. |
|
| 283 |
-
|
| 284 |
-
### 📂 System, Paths & Network Settings
|
| 285 |
-
| Variable | Default | Description |
|
| 286 |
-
|---|---|---|
|
| 287 |
-
| `WEBHOOK_PORT` | `9000` | Port used to listen for webhooks and Bazarr requests. |
|
| 288 |
-
| `PUID` / `PGID` | `99` / `100` | Run container as a specific user/group (helps with file permissions). |
|
| 289 |
-
| `DEBUG` | `True` | Outputs extra logs, helpful for troubleshooting paths or webhook hits. |
|
| 290 |
-
| `RELOAD_SCRIPT_ON_CHANGE` | `False` | (Dev) Auto-reloads uvicorn if `subgen.py` is edited. |
|
| 291 |
-
| `UPDATE` | `False` | (Standalone) Will pull the latest `subgen.py` from repo via `launcher.py`. |
|
| 292 |
-
| `USE_PATH_MAPPING` | `False` | Set to True if your media server and Subgen map their volumes differently. |
|
| 293 |
-
| `PATH_MAPPING_FROM` | `/tv` | Example: The media path on Plex. |
|
| 294 |
-
| `PATH_MAPPING_TO` | `/Volumes/TV` | Example: What Subgen natively sees that same path as. |
|
| 295 |
-
| `MODEL_PATH` | `./models` | Path where AI models are downloaded and stored. |
|
| 296 |
-
|
| 297 |
-
### 🎬 Media Server Integration (Metadata Refreshing)
|
| 298 |
-
*Required if you want Subgen to automatically generate Subtitles off of Webhook Events from Plex or Jellyfin or to tell Plex or Jellyfin to refresh the show's metadata so the subtitle immediately appears after generation.*
|
| 299 |
-
| Variable | Default | Description |
|
| 300 |
-
|---|---|---|
|
| 301 |
-
| `PLEX_SERVER` | *(None)* | Local Plex address (e.g., `http://192.168.1.100:32400`). |
|
| 302 |
-
| `PLEX_TOKEN` | *(None)* | Your Plex Token for API access. |
|
| 303 |
-
| `JELLYFIN_SERVER` | *(None)* | Local Jellyfin address (e.g., `http://192.168.1.100:8096`). |
|
| 304 |
-
| `JELLYFIN_TOKEN` | *(None)* | Generated API token from Jellyfin UI. |
|
| 305 |
-
|
| 306 |
-
---
|
| 307 |
-
|
| 308 |
-
## 🌎 Supported Audio Languages (via OpenAI)
|
| 309 |
-
Afrikaans, Arabic, Armenian, Azerbaijani, Belarusian, Bosnian, Bulgarian, Catalan, Chinese, Croatian, Czech, Danish, Dutch, English, Estonian, Finnish, French, Galician, German, Greek, Hebrew, Hindi, Hungarian, Icelandic, Indonesian, Italian, Japanese, Kannada, Kazakh, Korean, Latvian, Lithuanian, Macedonian, Malay, Marathi, Maori, Nepali, Norwegian, Persian, Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovenian, Spanish, Swahili, Swedish, Tagalog, Tamil, Thai, Turkish, Ukrainian, Urdu, Vietnamese, and Welsh.
|
| 310 |
-
|
| 311 |
-
---
|
| 312 |
-
|
| 313 |
-
## 🪲 Known Issues
|
| 314 |
-
* It uses trained AI models; there *will* occasionally be mistranslations or hallucinations based on background noise.
|
| 315 |
-
|
| 316 |
-
## ❤️ Credits
|
| 317 |
-
* [Whisper.cpp](https://github.com/ggerganov/whisper.cpp) for original implementation
|
| 318 |
-
* Google & FFmpeg
|
| 319 |
-
* [stable-ts](https://github.com/jianfch/stable-ts) & [faster-whisper](https://github.com/guillaumekln/faster-whisper)
|
| 320 |
-
* [Whisper ASR Webservice](https://github.com/ahmetoner/whisper-asr-webservice) for Bazarr HTTP webhook logic.
|
| 321 |
-
* Community Contributors
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Test
|
| 3 |
+
emoji: 🌍
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: mit
|
| 9 |
+
short_description: tew
|
|
|
|
| 10 |
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|