Table of Contents
- How-to guides
- Turn on unanchored repair for a dub-only show
- Queue a whole library, in watch order
- Redo an episode from scratch
- Recover an episode that crashed
- Stop the container without losing work
- Resolve a mux recovery marker
- See why an episode was not muxed
- Hold a show until you have reviewed it
- Fix a repair stage that silently does nothing
- Repair with a hosted model
- Use a decision model for glossary verification
- Triage the review queue
- Give a show without arc names a wiki scope
- Choose a quantisation for your card
- Sign in and manage accounts
- Recover an administrator account
- Point a show at its wiki
- Run only what you queue
- Connect Sonarr and Radarr
- Configure LLM connections
- Restart the container from the web UI
- Share your glossaries and verdicts
- Report a problem
How-to guides
Recipes. Each solves a single problem and assumes a working install — if you do not have one, start with Your first show.
Turn on unanchored repair for a dub-only show
Problem: your copies have an English dub but no English subtitle track for the Japanese audio. The repair stage has nothing to anchor against, refuses every line, and mangled names stay on screen.
Check whether this is you. List an episode's subtitle tracks:
ffprobe -v error -select_streams s \
-show_entries stream=index:stream_tags=language,title \
-of default=noprint_wrappers=1 "Show - S01E01.mkv"
An English track carrying full dialogue means you are anchored and should not do this. A Signs and Songs track only counts as no reference.
Seasons of one show can differ. Check the season you are about to process.
Do it. Add one key to that show's glossary file:
{
"show": "Show Name",
"unanchored_repair": true,
"names": ["..."]
}
The next repair pass sends glossary-only prompts for unanchored lines instead of skipping them.
Know the trade. Glossary-only repair can fabricate names — measured turning Oimo into
Zoro. Review the results rather than turning this on and walking away. Reasoning:
Why it works this way.
There is also a global REPAIR_UNANCHORED variable. It has been deployed library-wide
on the reference install since 2026-09-06 (see common.py's v10 changelog note) --
every show without an explicit unanchored_repair field in its glossary is repaired
unanchored by default there. Prefer the per-show glossary field for any new
install: it is committed to git and reviewable, where the global flag is host
configuration that a git pull cannot show you. If an unanchored repair ships
something wrong, the recovery is a reject verdict recorded with decisions.record
followed by review_apply.py, not disabling the flag.
Queue a whole library, in watch order
Problem: the default order spends hours on seasons you watched years ago before reaching the arc you are on.
Choose the shows and their order in /config/anime_order.txt, one folder name per line.
# comments and blanks are ignored:
One Pace (1999)
Cowboy Bebop (1998)
# Trigun (1998) <- queued but paused
Jump to where you actually are with /config/season_priority.txt:
# Show folder name : start season
One Pace (1999):20
Seasons at or after the start go first, ascending; earlier ones wrap around after. The same episodes, resequenced so the next arc lands soonest.
This file has no default path. Point at it explicitly:
SEASON_PRIORITY_FILE: /config/season_priority.txt
Without that variable the log says watch-order disabled and the file is never read.
SEASON_START is a global fallback for when you have no per-show file.
When you move further along, bump the number and restart the container.
Redo an episode from scratch
The pipeline never reads its own previous output here: stages that look at embedded subtitles skip the track named Dubtitles, and the mux replaces the old Dubtitles track in the same pass that adds the new one, so re-running needs no separate strip step for the old track.
Library-wide regeneration follows the pipeline's version stamps, TRANSCRIBE_VERSION and TEXT_VERSION in common.py. When a release raises one, episodes whose stamp records an older version are redone on later sweeps and their track is replaced in place; a failed run leaves the old track untouched. The CHANGELOG says which releases changed them.
Delete its sidecars and completion stamp:
rm "Show - S01E05".dubtitles.done \
"Show - S01E05".eng.dubtitles.srt \
"Show - S01E05".eng.dubtitles.ass \
"Show - S01E05".dubtitles.conf.json
The next sweep re-transcribes it.
To redo only the text, not the audio pass, keep .dubtitles.words.json. Word-level
confidences live there, so the text tier replays without the GPU.
This does not remove the already-muxed track. To strip it from the video first:
mkvmerge -o out.mkv --subtitle-tracks '!<id>' in.mkv
Recover an episode that crashed
Problem: one episode is skipped every sweep.
A hard crash leaves a poison marker so the pipeline does not loop on it:
ls "Show - S01E05".dubtitles.fail
cat "Show - S01E05".dubtitles.crash.json
The crash file names the exception. When you have dealt with it — or want to try anyway — delete the marker:
rm "Show - S01E05".dubtitles.fail
From 0.2.2, stopping the container with docker stop no longer leaves this marker, so one now
means a real crash. A SIGKILL or a power cut during transcription can still leave one. See
Stop the container without losing work.
Stop the container without losing work
Problem: you stop the container on a schedule or by hand, and an episode that was being transcribed is skipped from then on.
Before 0.2.2 the entrypoint ignored SIGTERM. docker stop waited out its grace period while the
loops kept starting new episodes, then sent SIGKILL. The episode killed mid-transcription kept
its .dubtitles.fail marker, so every later sweep skipped it. From 0.2.2 the container stops
softly: it starts no new work, lets the unit already running finish, and exits 0.
-
Set the grace period above your longest single unit of work. That is one episode's transcription, or one mux including a cross-device copy. Start with 900 seconds and tune it from your logs, using the time between episode start lines and the mux timestamps.
docker stop -t 900 dubtitle-builder -
Check how it ended. The exit code is 0 after a soft stop and 137 if the grace ran out and SIGKILL landed. The container log ends with
soft stop complete.docker inspect -f '{{.State.ExitCode}}' dubtitle-builder
If you run a nightly window, deploy/ has the systemd units for it. dubtitlerr-window-open
runs docker start at 00:00 and dubtitlerr-window-close runs docker stop -t 900 at 10:00
(America/New_York), each from its own timer. The close unit logs the exit code, prints a warning
when it is not 0, and deletes orphan *.muxtmp.mkv files. It skips any episode that has a
.dubtitles.mux-recovery marker. The units use the author's container name and library path, so
edit those and the times before you install them.
Releases up to 0.2.2 check the stop flag only before a glossary step starts, so an acquire step
that is already running ends at its own end or at ACQUIRE_TIMEOUT. Set the grace period
accordingly or stop between steps.
Resolve a mux recovery marker
Problem: the merge pass reports recovery pending for an episode and will not touch it.
For an .mkv source, the muxed file replaces the original. When the rename crosses
filesystems, mux falls back to a copy that overwrites the episode in place. If that copy fails
partway, the episode file may be damaged and the temp file may be the only complete copy. Mux
then keeps the temp file as <episode>.muxtmp.mkv.recovered, writes
<episode>.dubtitles.mux-recovery, and skips that episode on every pass until you resolve it.
Each pass reports MERGE PASS INCOMPLETE while the marker exists.
-
Read the marker. The
keptfield is the path of the complete copy.cat "Show - S01E05".dubtitles.mux-recovery -
Check that the kept file plays and has the tracks you expect.
ffprobe "<the path from kept>" -
Move the kept file over the episode's
.mkv, then delete the marker.mv "<the path from kept>" "Show - S01E05.mkv" rm "Show - S01E05".dubtitles.mux-recovery
If the kept file does not play either, restore the episode from your own copy of the release and delete the marker. The next pass treats the episode like any other.
See why an episode was not muxed
Problem: an episode has an .srt but never gets muxed.
Each stage records its outcome beside the video:
cat "Show - S01E05".dubtitles.stages.json
Read the stages in order (repair, signs, mux). The first one with a failed outcome is the
reason mux was skipped. Stage outcomes lists which outcomes count as
failures. The merge pass log has a matching skip mux: line, for example
skip mux: repair failed (...).
Fix the cause. You do not need to delete anything: the merge pass clears a stage's record before it runs that stage again, and a failed episode is retried on every pass.
Hold a show until you have reviewed it
Problem: you do not want unreviewed output written into videos for a show you care about.
REVIEW_GATE_SHOWS: "One Pace (1999):Cowboy Bebop (1998)"
Colon-separated directory names. Those episodes are transcribed and repaired as usual but are not muxed until their review queue is settled.
A hold older than REVIEW_GATE_STALE_DAYS (default 7) is reported loudly and stays held.
The timer buys a warning, never a release — auto-releasing unreviewed output is the thing
the gate exists to prevent.
Empty by default: an install that has not opted in behaves exactly as before.
Fix a repair stage that silently does nothing
Problem: the pipeline runs, the log shows repair targets, and every line comes back unchanged. No errors.
Check the model is actually replying:
curl -s http://127.0.0.1:8090/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"Reply with the word ok"}],"max_tokens":8}' \
| python3 -m json.tool
Look at choices[0].message. Two failures look identical from the pipeline's side:
| What you see | Cause | Fix |
|---|---|---|
content empty, reasoning_content full |
The model is thinking and never answers | --jinja and --chat-template-kwargs '{"enable_thinking":false}' |
content empty, nothing else |
The chat template was never applied | --jinja |
--jinja is required for chat_template_kwargs (specifically enable_thinking:false,
which repair.py always sends) to take effect at all. Without it the server loads, answers
/health with 200, and a thinking-capable model — qwen3-4b-instruct, the default,
included — spends its whole budget on reasoning and returns empty content forever.
Do not use /health as a readiness check. It reports 200 while weights are still
loading. Ask for a real completion instead, as above.
Repair with a hosted model
Problem: you have a key for an OpenAI-compatible API and want repair to use it instead of a model you serve yourself.
Know where your text goes. Every repair request carries the dub line, the lines around it, the glossary names and the overlapping fansub line. All of it goes to the provider. Read the provider's data terms before you point a real library at it.
1. Pick a model that answers in one short line. Repair asks for one corrected line. A model without reasoning works best, or one whose reasoning you can switch off. A reasoning model that spends its whole token budget thinking returns empty content, and repair counts that as the backend being unreachable.
2. Give the container the key by name. Put the key in an environment variable on the host
and pass that variable through. REPAIR_OPENAI_KEY_ENV holds the variable's name; the key
itself stays out of config files, command lines and logs.
environment:
REPAIR_BACKEND: openai
REPAIR_OPENAI_URL: https://api.example.com/v1/chat/completions
REPAIR_MODEL: vendor/model-x
REPAIR_OPENAI_KEY_ENV: EXAMPLE_API_KEY
EXAMPLE_API_KEY: ${EXAMPLE_API_KEY}
Compose fills ${EXAMPLE_API_KEY} from your shell or from a .env file beside compose.yaml.
3. Switch reasoning off if the model reasons. Put the provider's switch in
REPAIR_EXTRA_BODY. The switch differs by provider, so read the provider's documentation. As
one example, LongCat's API accepts {"thinking":{"type":"disabled"}}.
4. Try a few lines before a whole episode. tools/bakeoff.py sends real target lines from
one episode to the model and scores each reply with repair's own gate:
python3 tools/bakeoff.py --conf "<stem>.dubtitles.conf.json" \
--glossary "glossaries/<Show>.json" \
--openai-url https://api.example.com/v1/chat/completions \
--key-env EXAMPLE_API_KEY \
--extra-body '{"thinking":{"type":"disabled"}}' \
--models vendor/model-x --limit 12
It ends with a table of results. If most lines come back as <EMPTY ...> or <ERROR ...>, fix
that first. <ERROR rate-limited ...> means the provider is throttling you, and
<ERROR truncated ...> means the model ran out of tokens before it answered, so reasoning is
still on or REPAIR_MAX_TOKENS is too low.
5. Run one episode and read the summary. Queue one show and wait for repair to finish an
episode. Then open <stem>.dubtitles.repair-summary.json. Repair worked when unreachable is
0 and repaired is above 0. llm_empty counts the targets the model answered with nothing,
and rejected_4xx counts the ones the provider refused as a request. <stem>.dubtitles.stages.json
shows the stage as ok.
6. If repair refuses an episode. The stage shows backend-unreachable and the .srt is
left as it was. The log says why: too many failed targets, too many in a row, or the episode
deadline. When repair refuses an episode lists each rule and its
variable. The episode is tried again on the next pass.
Use a decision model for glossary verification
Problem: the local model that checks glossary names against the wiki picks wrong titles. On a rebuild of the One Pace glossary it wrote 106 expansions, 13 of them right. A decision model picks among the wiki's candidates and reports how confident it is; on the same audit it wrote 87 expansions, 38 of them right.
Know where your text goes. Each decision sends the show name, the term and the candidate
wiki titles to the provider. No dialogue goes. CommandCode's typesafe/jev, the model the
maintainer uses, bills per call; OpenRouter's inception/mercury-decide:free does not, and in
testing it wrote few names, most of them right.
1. Give the container the key by name. The key lives in a host environment variable. Config carries only the variable's name.
environment:
VERIFY_BACKEND: decision
VERIFY_DECISION_MODEL: typesafe/jev
COMMANDCODE_API_KEY: ${COMMANDCODE_API_KEY}
VERIFY_DECISION_KEY_ENV defaults to COMMANDCODE_API_KEY for CommandCode models and
OPENROUTER_JEV_API_KEY for OpenRouter ones. Set it only when you use a different name.
2. Try it on a copy. Verify rewrites the glossary it is given.
cp "/config/glossaries/<Show>.json" /tmp/<Show>.try.json
python3 glossary_verify.py /tmp/<Show>.try.json --force
3. Read the last lines. Verify prints one summary line,
decision backend: model=typesafe/jev calls=986 ok=985 failures=1 fallbacks=0 pending=1. A
failed call leaves its term pending for the next sweep. After five failed terms in a row the run
stops calling the provider (VERIFY_DECISION_BREAKER), so an outage costs five requests and not a
night's worth. VERIFY_DECISION_FALLBACK=local lets the local model answer instead.
4. Know what acquisition does. glossary_acquire.py asks a same-entity question. On the
audit set the decision model was worse than the local one at it (47% against 72%), so acquire
stays on the local model when verify uses the decision model. ACQUIRE_BACKEND=decision changes that.
Triage the review queue
Problem: the review queue is long, and most of it is not worth your time.
Glossary flags. Run the review on the glossary and the show folder:
python3 glossary_acquire.py "/config/glossaries/<Show>.json" "/media/Anime Library/<Show>" --review
Without --apply it only shows what it would do. Add --apply to write your answers. Decisions
come first, in this order: respelling-needs-review, common-word, not-in-arc-pages,
low-confidence, possessive_floor_crossing. Terms with no wiki candidate are collapsed into one
line, because there is nothing to accept or reject. --all lists them, and --prune-no-match
removes the stored ones.
If a stage holds the glossary while you answer, your answers wait up to ten minutes, and are then
saved beside the glossary and applied at the next --review. An answer is applied only to the
proposal you saw. If the term was flagged again with another canonical in the meantime, the answer
is skipped and the log says so.
Repair rejections. The review page lists them. A rejection that changed more than six words is
kept in the file but hidden from the default view, because in a blind sample of 100 real
rejections no acceptable fix needed more than that. Show them with the all-reasons view. Raise
REPAIR_AUTO_DISMISS_WORDS to see more by default, or set it to off to see all.
What to expect. On the Wano run, about four in five rejections were right, so the queue is mostly confirming a guard. The ones worth finding are casing, punctuation and single-name respellings. See Why the queues are smaller.
Give a show without arc names a wiki scope
Problem: the arc stage names each season's arc from its season.nfo. Most shows have no such
name, so the stage has nothing to scope the wiki lookup by.
1. Pick the rung that fits the wiki.
| The wiki has | Use |
|---|---|
| An index page with arcs and their episode numbers | arc_index |
| One page per season | season_page |
| Little structure, or the show has one season | whole_wiki |
2. Add a wiki_scope block to the show's glossary. For Naruto Shippuden:
{
"wiki_scope": {
"rung": "arc_index",
"wiki": "https://naruto.fandom.com/api.php",
"index_page": "Plot of Naruto",
"part": "Part II",
"season_offsets": { "2": 32, "3": 53 }
}
}
The wiki's table restarts its episode numbers in each part, so part is required when the page
has several, and season_offsets maps your season's episode numbers to the table's. Library
seasons often do not line up with the wiki's arcs, so the scope is picked by episode number.
3. Check the file names. Season and episode scopes read SxxExx from the video file names. A
file without one gets no scope.
4. Tag once by hand and read the result.
python3 glossary_verify.py "/config/glossaries/<Show>.json" --tag-arcs
The glossary now has arc_titles and arc_coverage. A scope that failed, came back partial or
could not be parsed stores nothing and appears in arc_titles_missing. Fix that before you rely
on the stored titles. Set GLOSSARY_ARC_TAGS=1 to run the same step every night.
5. For a show that has arcs but some seasons that are not arcs, tell the stage what to do with
them. One Pace's Gaimon and Water Seven seasons are the examples: Gaimon has no wiki arc page,
and Water Seven's page is named Water 7.
{
"arc_aliases": { "Water Seven": "Water 7", "Fishman Island": "Fish-Man Island" },
"arc_waived": ["Gaimon", "The Adventures of Buggy's Crew", "The Trials of Koby-Meppo"]
}
VERIFY_ARC_GATE=1 stays off until arc_titles_missing is empty. On the audit set the gate stopped
45 of 119 wrong writes and 8 of 42 right ones, so it is the weaker of the two write guards.
Choose a quantisation for your card
Problem: you want Whisper and the repair model resident at once on one card.
This project runs Q6_K. On-disk weights, measured 2026-09-02:
| Quantisation | Size on disk |
|---|---|
Q8_0 |
4.0 GB |
Q6_K |
3.1 GB |
Q5_K_M |
2.7 GB |
Q4_K_M |
2.4 GB |
On a 6 GB card, Q8_0 leaves roughly 2 GB — tight alongside Whisper, and not necessarily enough depending on your Whisper model and compute type. Q6_K buys back most of a gigabyte, which is why it is the one this project settled on.
Options, cheapest first:
- A smaller quantisation. Q5_K_M or Q4_K_M go further still. The quality cost below Q6_K is not measured here; the table above is sizes, not quality.
- Two cards. Whisper on one, the repair model on the other. Nothing assumes they share a device — the repair stage talks to an HTTP endpoint.
- Sequential. Run the transcription sweep and the merge sweep at different times, one
model resident at a time.
generate.pyloads Whisper lazily and its process exits between shows, so this costs wall-clock rather than quality.
Check what is actually resident before blaming the pipeline for an OOM:
nvidia-smi --query-gpu=memory.used,memory.total --format=csv
If another process holds the card, Whisper can CUDA-OOM. The pipeline exits cleanly and the loop restarts with a fresh context, so it self-heals once VRAM frees — but do not run two transcriptions on one small card at once.
Sign in and manage accounts
Problem: you need to control access to the review workspace, add user accounts, or rotate keys.
First-run setup. On a fresh install without accounts, browse to http://<host>:8842. The server opens /review/setup to create your initial administrator account. Alternatively, set REVIEW_USERNAME and REVIEW_PASSWORD (or REVIEW_PASSWORD_FILE) in compose.yaml to seed the admin account once on first boot.
Sign in and roles. Sign in with your username and password at http://<host>:8842/review.
- admin: manages accounts, changes settings, tests connections, and rotates the admin API key.
- user: reviews episodes, submits verdicts, and changes their own password.
- Read and write routes both require authentication.
Manage user accounts. Signed in as an administrator, open Settings > General (#/settings/general) and scroll to Accounts. You can create accounts, promote or demote users between admin and user, reset passwords, or delete accounts. The server refuses to delete or demote the last remaining administrator.
Change your password. Click your username in the navigation bar and select Change Password.
Automate with the admin API key. External scripts send the X-Api-Key header instead of browser cookies. The key is stored in /config/apikey. You can view, copy, or reset it under Settings > General > Security.
Disable authentication. Set REVIEW_AUTH=off in your container environment only if you run DubTitlerr on an isolated, trusted network.
Recover an administrator account
Problem: you forgot your administrator password or got locked out of the web UI.
Run the recovery tool inside the container. Execute review_users.py reset-admin with your administrator username:
docker compose exec dubtitlerr python3 review_users.py reset-admin <username>
The command generates a new 16-character password that stays until changed, prints it to your terminal, and clears existing sessions for that account. Sign in with the new password and update it when you are ready.
If users.json is unreadable or corrupt, the tool moves the file aside as users.json.corrupt-<timestamp> and creates a fresh administrator account with <username>.
Point a show at its wiki
Problem: automatic wiki detection picks the wrong wiki or you want to set a custom MediaWiki API endpoint for a show.
Requirement: the show must already have a glossary file in GLOSSARY_DIR. Shows without a glossary cannot set a wiki URL here yet.
1. Open the Glossary page. In the web UI, open Glossary (#/glossary) and select your show.
2. Enter the wiki URL. In the Wiki field above the term tables, enter the MediaWiki site or API URL (for example https://naruto.fandom.com or https://naruto.fandom.com/api.php). Leaving the field empty clears the override and restores automatic detection.
3. Test the URL. Click Test to verify the endpoint before saving. DubTitlerr queries the siteinfo API and displays the confirmed site name.
4. Respect URL constraints. URLs must use https unless WIKI_ALLOW_HTTP=1 is set in the container environment. The server refuses loopback addresses, private network IPs, link-local addresses, and embedded credentials.
5. Save the glossary. Click Save to write the wiki URL to the show's glossary JSON file.
Run only what you queue
Problem: you want DubTitlerr to process only episodes you explicitly queue, instead of sweeping your entire media library continuously.
1. Turn off library sweep. In the web UI, open Settings > Schedule and set Sweep the whole library (LIBRARY_SWEEP) to Off. You can also set LIBRARY_SWEEP: "false" in compose.yaml.
2. Know what changes.
- The generation loop disables root library walks and only processes requests waiting in the run queue.
- The merge pass only checks show directories with requests that are pending, running, or finished in the last 7 days, leaving the rest of the library untouched.
3. Queue episodes. Open the Runs page (#/runs) to queue a show, season, or episode regex, or trigger runs automatically through Sonarr and Radarr webhooks.
Connect Sonarr and Radarr
Problem: you want newly downloaded episodes queued automatically when Sonarr or Radarr imports them.
1. Set the webhook token. In compose.yaml (or in Settings > Connect > Webhook), set WEBHOOK_TOKEN:
WEBHOOK_TOKEN: your-secret-webhook-token
When this variable is unset, webhook routes return 404.
2. Map remote paths if needed. If Sonarr or Radarr runs with different mount paths, set REMOTE_PATH_MAPPINGS:
REMOTE_PATH_MAPPINGS: "/data/anime=/media/Anime Library;/downloads=/media/downloads"
3. Add the webhook notification in Sonarr or Radarr. Go to Settings > Connect > Add Notification > Webhook:
- URL:
http://<host>:8842/api/webhook/sonarr(or/api/webhook/radarr) - Method:
POST - Headers: add
X-Webhook-Token: your-secret-webhook-token(or append?token=your-secret-webhook-tokento the URL) - Triggers: enable On Download and On Upgrade.
Click Test in Sonarr or Radarr to confirm the connection.
Configure LLM connections
Problem: you want to use local or remote LLM backends without restarting the container or editing Compose files.
1. Open Connections. In the web UI, go to Settings > Connections (#/settings/connections).
2. Add a connection.
- Enter a name and select a kind (
llama.cpp,Ollama, orOpenAI-compatible). - Set the endpoint URL and model name.
- For OpenAI-compatible providers, enter the API key in the write-only key field. Keys are stored in
secrets.json(mode 0600) and never returned to the browser. - Click Test to send a probe completion and verify the endpoint.
3. Assign stages. Pick which connection runs each stage (Repair, Restore, Verify, Decision, and Acquire). Stages without an assigned connection keep their container environment defaults.
Restart the container from the web UI
Problem: you changed a setting marked "Restart required" and want to apply it without terminal access.
1. Save your changes. When you save a restart-required setting (such as port, bind address, or webhook paths), DubTitlerr prompts you with two choices:
- Restart Now: asks the builder to finish the current episode in flight and exit cleanly. Docker brings the container back up automatically under
restart: unless-stopped. - Restart Later: keeps running the current process and displays a "Restart pending" banner until the next container restart.
2. Reconnection. While the builder restarts, the web UI displays a reconnecting overlay and resumes your session once the new instance answers.
Share your glossaries and verdicts
Problem: curated glossaries and reviewed seasons are trapped on one machine.
GLOSSARY_DIR and DECISIONS_DIR are plain directories of JSON, one file per show, designed
to be committed to git. A git pull on the host is what makes them current: the container
reads whatever is in the mount.
cd ~/dubtitlerr/glossaries && git init && git add . && git commit -m "glossaries"
The admin API key is deliberately stored beside DECISIONS_DIR (at /config/apikey), never inside it, so a
credential never rides along with a directory you publish.
Community glossaries live in their own repository with a pull-request path for contributions.
Report a problem
Include:
- The log lines around the failure.
.dubtitles.repair-summary.json— it names the model, the rules and the counts..dubtitles.crash.json, if there is one.- Whether the show is anchored or unanchored, plus the
ffprobetrack listing from the first recipe on this page.
Do not include the video.