summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-node/src/meshbay_node/ops.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-24 15:57:41 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-24 15:57:41 +0200
commitc5585beab3d6adefaa2ef9444946dd3816960a7c (patch)
treea321e540c2db0458716d526e4a045fca123937b2 /packages/meshbay-node/src/meshbay_node/ops.py
parent317f09328ed8bf20148b707470c9b0fe82e59575 (diff)
downloadmeshbay-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 'packages/meshbay-node/src/meshbay_node/ops.py')
-rw-r--r--packages/meshbay-node/src/meshbay_node/ops.py43
1 files changed, 29 insertions, 14 deletions
diff --git a/packages/meshbay-node/src/meshbay_node/ops.py b/packages/meshbay-node/src/meshbay_node/ops.py
index 6848e3a..a232ba2 100644
--- a/packages/meshbay-node/src/meshbay_node/ops.py
+++ b/packages/meshbay-node/src/meshbay_node/ops.py
@@ -733,23 +733,23 @@ async def set_enabled_apps(state: dict, group_id: str, apps: list[str]) -> dict:
# ── TMDB config (Videos app) ─────────────────────────────────────────────────
-async def set_tmdb_config(state: dict, enabled: bool, token: str | None = None,
+async def set_tmdb_config(state: dict, token: str | None = None,
language: str | None = None) -> dict:
"""
- Whether the node calls TMDB at all, whether it uses a custom API token
- instead of the shipped default, and in what language it queries TMDB
- (docs/mediacenter.md §5.5).
+ Whether the node uses a custom API token instead of the shipped default,
+ and in what language it queries TMDB (docs/mediacenter.md §5.5).
Node-wide (roster.py group_settings, group_id="") rather than per-group
- like set_member_upload/set_enabled_apps: TMDB is one operator's budget,
- one credential and one shared cache, not a per-group or per-viewer
- concern. `token=""` explicitly clears a previously-set custom token
- (reverts to the shipped default); `token=None` leaves whatever was
- there unchanged. Same discipline for `language`.
+ like set_member_upload/set_enabled_apps: the token and the shared-cache
+ language are one operator's budget and one credential, not a per-group
+ or per-viewer concern. Whether TMDB is used *at all* is the per-group
+ decision set_tmdb_enabled below makes instead. `token=""` explicitly
+ clears a previously-set custom token (reverts to the shipped default);
+ `token=None` leaves whatever was there unchanged. Same discipline for
+ `language`.
"""
roster = _roster(state)
- await roster.set_tmdb_config(enabled, token, language, set_by=state.get("node_user_id", ""))
- state["tmdb_enabled"] = enabled
+ await roster.set_tmdb_config(token, language, set_by=state.get("node_user_id", ""))
# `token=None` means "leave whatever was there" (§ set_tmdb_config's own
# docstring) — so the customized flag only changes when a value (a real
# token, or "" to clear one) was actually given.
@@ -757,15 +757,30 @@ async def set_tmdb_config(state: dict, enabled: bool, token: str | None = None,
state["tmdb_token_customized"] = bool(token)
if language is not None:
state["tmdb_language"] = language
- log.info("TMDB config: enabled=%s custom_token=%s language=%s",
- enabled, bool(token), language or state.get("tmdb_language", ""))
+ log.info("TMDB config: custom_token=%s language=%s",
+ bool(token), language or state.get("tmdb_language", ""))
return {
- "enabled": enabled,
"token_customized": state.get("tmdb_token_customized", False),
"language": state.get("tmdb_language", ""),
}
+async def set_tmdb_enabled(state: dict, group_id: str, enabled: bool) -> dict:
+ """
+ Whether TMDB lookups run for this group at all (docs/mediacenter.md
+ §5.5) — per-group, unlike set_tmdb_config above: an operator running a
+ real media library alongside test/demo groups on one node wants
+ outbound TMDB traffic (and API quota) spent for the one that needs it,
+ not all of them just because one process serves both.
+ """
+ roster = _roster(state)
+ ctx = _group_ctx(state, group_id)
+ await roster.set_tmdb_enabled(group_id, enabled, set_by=state.get("node_user_id", ""))
+ ctx["tmdb_enabled"] = enabled
+ log.info("TMDB enabled for group %s: %s", group_id[:8], enabled)
+ return {"enabled": enabled, "group_id": group_id}
+
+
async def set_video_root(state: dict, group_id: str, path: str) -> dict:
"""
Which folder (possibly a subfolder of a shared root) is the Videos app's