docs(arr): settle the two open §15 questions

Forced and SDH get no sidecar name of their own: one language, one
sidecar, and a forced track is ignored where a plain one exists. That
makes the database constraint fall out rather than needing a scheme.

The OpenAI-compatible backend's base URL and model become database rows.
It is not "OpenAI" — it is any endpoint speaking that shape, llama.cpp
included — so which one is in use is something to try and change, not a
property of the deployment. Only the API key stays in the environment.
This commit is contained in:
Miguel Palhas
2026-08-25 08:17:36 +01:00
parent 84dc5ba27b
commit ab001b512f
+21 -3
View File
@@ -800,6 +800,12 @@ killed it, so the manual view described in §9.3 works unchanged for subtitles.
on-screen signs; it never satisfies a want and arr never goes looking for one.
An SDH track is complete and satisfies, ranked below a plain subtitle.
Neither gets its own sidecar name. A language is satisfied by exactly one
sidecar, so `<video>.<lang>.srt` needs no segment distinguishing forced from
plain from SDH — where a plain subtitle exists for a language, the forced one
is ignored rather than kept beside it. The database says the same thing: one
sidecar row per (media file, language).
**Translation.** When no provider has a wanted language, arr translates
immediately — there is no waiting window. The source is an existing subtitle:
a downloaded one, or one extracted from a text-format embedded track. Being
@@ -827,6 +833,10 @@ property — with the app stopped, the filename says which subtitles are
machine-made. Folder-level delete stays atomic because sidecars are inside the
folder.
`.mt` is the only optional segment. One language, one sidecar: a second
subtitle for a language arr already has is refused, and replacing one is the
manual delete-then-fetch §15's no-upgrade rule already describes.
**Sync.** `alass` runs on every fetched and every translated subtitle. It is a
single small binary invoked like `ffprobe`, so it costs nothing at rest. It
reports no confidence value, so its output is accepted unless it is
@@ -834,9 +844,17 @@ implausible — a shift beyond 60 seconds, or cues lost — in which case the
unsynced original is kept and the file is flagged.
**Configuration.** Provider credentials and translator API keys are bootstrap
config or environment, per §10. Wanted languages, chosen engine, per-provider
enable and the daily budgets are database rows edited from `/settings` without
a restart.
config or environment, per §10 — a secret never becomes a database row. Wanted
languages, chosen engine, per-provider enable and the daily budgets are
database rows edited from `/settings` without a restart.
So is everything needed to point the OpenAI-compatible backend somewhere else:
its **base URL and its model name are database rows too**, not bootstrap
config. That backend is not "OpenAI" — it is any endpoint speaking that shape,
`llama.cpp` and a local gateway included, and which one is in use is a thing to
try and change, not a property of the deployment fixed at start-up. Only the
API key stays in the environment, and an endpoint that needs no key is a valid
configuration.
**Budgets.** A token bucket per provider and per translator, with a configured
daily allowance. The reconcile loop spends it newest-import-first, so enabling