diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-24 15:57:41 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-24 15:57:41 +0200 |
| commit | c5585beab3d6adefaa2ef9444946dd3816960a7c (patch) | |
| tree | a321e540c2db0458716d526e4a045fca123937b2 /docs/mediacenter.md | |
| parent | 317f09328ed8bf20148b707470c9b0fe82e59575 (diff) | |
| download | meshbay-c5585beab3d6adefaa2ef9444946dd3816960a7c.tar.gz | |
fix(node,hub): HEVC transcode fallback, live-add progress, per-group TMDB toggle
Three bugs found live testing the Videos app against a real HEVC/EAC3 show,
plus a design change requested afterward:
- Streaming always did "-c:v copy", which faithfully reports a source's real
hev1 codec string but is unplayable in a browser with no HEVC decoder
(most Chrome/Linux builds). The node now transcodes to H264 whenever the
probed codec is browser-incompatible (media_probe.py's new
BROWSER_INCOMPATIBLE_VIDEO_CODECS), with a `transcode_incompatible_video`
node.toml opt-out for operators who know their viewers already decode it.
- Dropping a whole season into an already-watched folder gave no scanning
indicator and no progress bar: IndexProgress was only ever updated by the
two bulk scan paths, never by the real-time per-file watchdog path
(_schedule_update/_debounce/_update_entry). That path now accounts a
"burst" the same way, without double-counting a file rewritten mid-debounce.
- A stray literal "0" rendered in the video detail modal when there was no
TMDB match (`meta.confidence` is 0, and `0 && x` renders "0" in JSX/htm,
not nothing) — `confident` is now a real boolean.
- Whether TMDB is used at all moves from a node-wide setting to per-group
(OP_TMDB_ENABLED/tmdb_enabled/tmdb_enabled_ack, scoped like OP_VIDEO_ROOT):
an operator running a real media-library group alongside test/demo groups
on one node wants outbound TMDB traffic for the one that needs it, not all
of them. The custom API token and query language stay node-wide, one
shared credential/cache (tmdb_config/OP_TMDB_CONFIG, unchanged reasoning).
MNP_VERSION 0.6 -> 0.7, additive.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LAmyXtc6dAADsH23ydXQpY
Diffstat (limited to 'docs/mediacenter.md')
| -rw-r--r-- | docs/mediacenter.md | 60 |
1 files changed, 51 insertions, 9 deletions
diff --git a/docs/mediacenter.md b/docs/mediacenter.md index 66232f8..0df115b 100644 --- a/docs/mediacenter.md +++ b/docs/mediacenter.md @@ -362,6 +362,25 @@ seen; the file appears in the index immediately with size/hash only, and an `index_sync` delta fills in the technical/parsed fields once ready — no scan is blocked waiting for it. +**Bug found live, 2026-08-24**: an operator moved a whole show's season into +an already-watched shared folder and saw no scanning indicator and no +progress bar at all — files just appeared one at a time, exactly as if +nothing were tracking the add. Root cause: `IndexProgress` (`scanning`/ +`scanned_bytes`/`total_bytes`) was only ever touched by the two *bulk* scan +paths — the initial walk and the periodic reconcile backstop, both of which +know their file list upfront. The real-time watchdog path +(`_schedule_update`/`_debounce`/`_update_entry`, one file at a time, each +independently debounced) never touched it at all — an omission, not a race: +dropping in ten files this way always gave zero feedback, indexing or not. +Fixed by accounting a "burst" the same real-time path creates: a file's size +is added to `total_bytes` the moment its debounce timer is first scheduled +(not on every re-trigger of the same path — a cancelled-and-rescheduled +timer must not double-count), and to `scanned_bytes` once its hash actually +finishes; `scanning` flips back off only once no debounce timers are pending +*and* no hash is still running, not just when the last timer fires — the +in-flight hash of a large file is the entire reason to show progress in the +first place. + ### 5.3 Thumbnail delivery — reuse the chunk path Since `thumb_hash` is a blake3 exactly like a file's own `id`, the cleanest @@ -471,20 +490,22 @@ made a revisit's fetch fast enough to *be* synchronous. ### 5.5 Node-wide config, not per-group -TMDB is one operator's budget and one credential, not a per-group concern, -so it does not belong in `group_settings` keyed by a real `group_id`. The -existing precedent for node-wide operator state stored in that same table is -already established (`desktop-client-v1.md` §6.3: *"the precedent exists: +The TMDB credential and query language are one operator's budget and one +shared cache, not a per-group concern, so they do not belong in +`group_settings` keyed by a real `group_id`. The existing precedent for +node-wide operator state stored in that same table is already established +(`desktop-client-v1.md` §6.3: *"the precedent exists: `roster.get_member("", user_id)` already authorizes the operator -node-wide"*) — so `tmdb_enabled` and an optional `tmdb_api_token` land in +node-wide"*) — so an optional `tmdb_api_token` and `tmdb_language` land in `group_settings` under the sentinel `group_id=""`, changed by a signed operator op (`OP_TMDB_CONFIG`, same shape as `OP_MEMBER_UPLOAD`/ `OP_APPS_ENABLED`), and broadcast in `node_status` (the node-wide channel, as opposed to the per-group `handshake_ack`) so every connected client, -across every group, sees whether TMDB is on without reconnecting. Absent -means the shipped default token, present with a token means "use this one -instead" — the same "absent means the old behaviour" discipline -`member_upload`/`apps_enabled` already follow. +across every group, sees the current token/language state without +reconnecting. Absent means the shipped default token, present with a token +means "use this one instead" — the same "absent means the old behaviour" +discipline `member_upload`/`apps_enabled` already follow. (Whether TMDB is +used *at all* used to live here too — moved per-group, below.) **Added 2026-08-24**: a third field, `tmdb_language` (e.g. `"fr-FR"`), travels the same way — one node-wide setting, not a per-viewer request. @@ -521,6 +542,27 @@ same — a second, English-forced details fetch only when a checked field (`overview`, `poster_path`, `genres`) comes back empty, merged field by field so a good localized field is never overwritten by the fallback. +**Whether TMDB is used at all, moved per-group, 2026-08-24**: an operator +running one real media-library group alongside several test/demo groups on +the same node found every group sharing one on/off switch meant there was +no way to spend TMDB quota and make outbound requests for the group that +actually needed it without doing the same for groups that didn't. Split +into its own signed op, `OP_TMDB_ENABLED`/`tmdb_enabled`/`tmdb_enabled_ack`, +scoped to `self._group_id` exactly like `OP_VIDEO_ROOT` — stored in +`group_settings` under the real `group_id` this time, not the `""` +sentinel, and surfaced in the per-group `handshake_ack` (`tmdb_enabled`, +already there — it simply reads a per-group value now) rather than +`node_status`. `tmdb_config`/`OP_TMDB_CONFIG` keep their name and shape for +the token/language, which stay node-wide for the reasoning above; only the +on/off switch moved. `TmdbClient` itself lost its own notion of "enabled" +entirely — every call site in `webrtc_server.py` (`_do_media_meta_request`, +`_do_season_meta_request`, `_do_tmdb_search_request`) now checks +`self._group_ctx().get("tmdb_enabled", True)` before ever calling it, and a +group with it off degrades exactly like "no client configured" already +did — zero confidence, empty search results, never an error, since a +member's Videos tab already has to handle "no TMDB match" as the ordinary +case (§4.1). + ### 5.6 `ALLOWED_APPS` `webrtc_server.py:1629` — add `"video"` to the frozenset. `DEFAULT_APPS` |