diff --git a/web_server.py b/web_server.py
index b80ff17c..d18b9d8f 100644
--- a/web_server.py
+++ b/web_server.py
@@ -37257,17 +37257,16 @@ def _emit_video_enrichment_status_loop():
the access log). No-op until the video engine is actually running, so this
never spins it up on the music side."""
from core.video.enrichment.engine import peek_video_enrichment_engine
- services = ('tmdb', 'tvdb', 'omdb')
while not globals().get('IS_SHUTTING_DOWN', False):
socketio.sleep(2)
eng = peek_video_enrichment_engine()
if eng is None:
continue
- for svc in services:
+ # Emit for EVERY registered worker (matchers + backfill: fanart / opensubtitles
+ # / ryd / sponsorblock) so new dashboard buttons get live status with no extra
+ # wiring here.
+ for svc, w in (eng.workers or {}).items():
try:
- w = eng.worker(svc)
- if w is None:
- continue
socketio.emit(f'enrichment:{svc}', w.get_stats())
except Exception as e:
logger.debug(f"Error emitting video {svc} status: {e}")
diff --git a/webui/index.html b/webui/index.html
index 457bce25..73bbbba0 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -504,6 +504,70 @@
+
+
+
+
diff --git a/webui/static/video/video-enrichment.js b/webui/static/video/video-enrichment.js
index c87db590..eedb06a5 100644
--- a/webui/static/video/video-enrichment.js
+++ b/webui/static/video/video-enrichment.js
@@ -17,7 +17,8 @@
// All four push status over the shared socket every 2s (server emits
// 'enrichment:') — including the standalone YouTube date enricher — so the
// browser never polls /api/video/enrichment//status.
- var SERVICES = ['tmdb', 'tvdb', 'omdb', 'youtube'];
+ var SERVICES = ['tmdb', 'tvdb', 'omdb', 'youtube',
+ 'fanart', 'opensubtitles', 'ryd', 'sponsorblock'];
function onVideoSide() {
return document.body.getAttribute('data-side') === 'video';
diff --git a/webui/static/video/video-worker-orbs.js b/webui/static/video/video-worker-orbs.js
index 06c1b146..39fe2a78 100644
--- a/webui/static/video/video-worker-orbs.js
+++ b/webui/static/video/video-worker-orbs.js
@@ -24,6 +24,10 @@
{ sel: '[data-video-enrich="tvdb"]', color: [168, 85, 247], id: 'tvdb' },
{ sel: '[data-video-enrich="omdb"]', color: [245, 197, 24], id: 'omdb' },
{ sel: '[data-video-enrich="youtube"]', color: [255, 59, 59], id: 'youtube' },
+ { sel: '[data-video-enrich="fanart"]', color: [228, 80, 154], id: 'fanart' },
+ { sel: '[data-video-enrich="opensubtitles"]', color: [34, 160, 121], id: 'opensubtitles' },
+ { sel: '[data-video-enrich="ryd"]', color: [239, 68, 68], id: 'ryd' },
+ { sel: '[data-video-enrich="sponsorblock"]', color: [0, 180, 160], id: 'sponsorblock' },
{ sel: '[data-video-manage-workers]', color: [168, 85, 247], hub: true },
];