processes/ -> playbooks/ (git mv preserves history; updated cross-refs in ROADMAP, README, subtitles playbook + scripts). playbooks/import-media/README.md v1.0 — 7-step import workflow: stage on onyx -> rsync to nullstone -> chmod -> verify scan -> Items/Counts bump -> optional subtitle pass -> run-log Cross-references docs/05/07/08, ADMIN-GUIDE, README. Mirrors the existing subtitles playbook structure (CHANGELOG + runs/_template). CHANGELOG v1.0 lists known gaps (bin/cleanup-import.sh and bin/normalize.py still doc-only, ROADMAP M6). First run logged: playbooks/import-media/runs/lilo-stitch-2002.md. Lilo & Stitch (2002) imported to /home/user/media/movies/, item c2f4aff133c1b9631500fadf293b0b2f, TMDb 11544, MovieCount 3 -> 4. LibraryMonitor didn't auto-fire — needed manual /Library/Refresh; playbook updated to make this an unconditional step. Source: 1080p BluRay HEVC 10-bit / EAC3 5.1 / 2x PGS embedded subs. Per quality bar (README.md:41) — passes.
3.3 KiB
3.3 KiB
Subtitle USER-G style — ARRFLIX
The bar every fetch should hit. If a recipe step would violate any of these, stop and ask before proceeding.
What lands on disk
- Exactly one English subtitle file per episode.
- Filename:
<videobasename>.eng.srt— no language-region tags (en-US), no flag stack on regular subs (no.sdh, no.forced, no.ccunless there genuinely is no plain-English option). - Format:
.srt(SubRip text). Skip.ass,.ssa,.vtt,.sup,.idxunless the source has nothing else; convert withffmpeg -map 0:s:0 -c:s srtin that case. - Encoding: UTF-8. Re-encode with
iconvif a sidecar comes back as cp1252 / windows-1250.
What gets picked
In order:
- English language —
eng/en. Never auto-picken-US/en-GBvariants over plainen; treat them equivalent for matching. - No SDH / Hearing Impaired — drop any sub flagged
hearing_impaired,sdh,cc. Only fall back to SDH if no plain-English option exists. - No machine / AI translation — drop
machine_translated,ai_translated. Hand-authored subs only. - No forced subtitles — drop
foreign_parts_only/Forcedunless the episode has English audio with foreign-language scenes that need translation (rare for US shows). - Frame-rate match — prefer entries whose declared fps matches the
source video (typically 23.976 for our masters). Treat
0.0as unknown and fall through to step 6. - Highest download count within the surviving candidates — proxies for "the version everyone agreed was best."
After fetch, eyeball-verify one sample episode per show plays in sync (±1 s on a known dialogue line) before declaring the show done.
What doesn't ship
- Multiple language tracks per episode (no German/French alternatives — English-only library).
- Director's commentary, behind-the-scenes, song-only subs.
- Subs that cover only a partial runtime (the partial-cover heuristic isn't scripted yet; spot-check duration vs episode runtime if a srt looks short).
- "All-episodes-in-one" mega-packs treated as a single episode's sidecar.
How the UI presents subs
The detail-page subtitle dropdown is shimmed via
web-overrides/index.html (markers SUB-LABEL-SHIM-BEGIN/END). Stock
Jellyfin shows e.g. English - SUBRIP - External - Default; the shim
collapses to English, with (Forced) / (SDH) / (Hearing Impaired)
suffixes only when those flags actually apply. Default is dropped — it's
redundant when there's only one stream per language.
Revert: bin/revert-sub-label-shim.sh.
Why these rules
- Boutique-release-group quality bar from
README.md: "every show and film is the best version I could put together." - One-language library = one stream per ep = no need to expose codec or source in UI.
- SDH/CC adds
[door slams],[music]etc. — distracting on first watch and not what someone reaches for unless they specifically need it. - Machine / AI translations are inconsistent and often wrong on slang or show-specific terms (esp. animated comedies).
- Frame-rate-matched subs sync without manual offset on first try; mismatch generally still works on NTSC (29.97 vs 23.976 are the same elapsed time) but hash-match or fps-match removes that gamble.