From 89df1a98db0a28f6be83174663dd4e27a5718b55 Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sun, 31 May 2026 21:52:31 -0400 Subject: [PATCH] ui: show resolution and codec counts in streams header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds height/codec fields to both Emby/Jellyfin and Plex session data, then surfaces them as chip groups (· 2 4K 3 1080p · 4 H.264 2 HEVC) in the streams card header alongside the existing device type bar. Co-Authored-By: Claude Sonnet 4.6 --- Plugin/unraid/include/media.php | 16 ++++++++++++++ Plugin/unraid/pages/monitor.php | 38 ++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/Plugin/unraid/include/media.php b/Plugin/unraid/include/media.php index b32ae54..fd9ae85 100644 --- a/Plugin/unraid/include/media.php +++ b/Plugin/unraid/include/media.php @@ -109,6 +109,12 @@ function vv_fetch_jf_sessions(array $srv): array { $method = $pm === 'DirectStream' ? 'Direct Stream' : 'Direct Play'; } + // Source video stream — resolution and codec of the file being played + $videoStream = null; + foreach ($item['MediaStreams'] ?? [] as $ms) { + if (($ms['Type'] ?? '') === 'Video') { $videoStream = $ms; break; } + } + $result[] = [ 'server' => $srv['name'], 'server_type' => $srv['type'], @@ -122,6 +128,8 @@ function vv_fetch_jf_sessions(array $srv): array { 'pos_sec' => (int)($pos / 10000000), 'dur_sec' => (int)($dur / 10000000), 'is_tc' => $tc !== null, + 'height' => (int)($videoStream['Height'] ?? 0), + 'codec' => strtolower($videoStream['Codec'] ?? ''), ]; } return $result; @@ -160,6 +168,12 @@ function vv_fetch_plex_sessions(array $srv): array { } $player = $m['Player'] ?? []; + $media0 = $m['Media'][0] ?? []; + $plexH = (int)($media0['height'] ?? 0); + if (!$plexH && !empty($media0['videoResolution'])) { + $vr = strtolower($media0['videoResolution']); + $plexH = $vr === '4k' ? 2160 : (int)$vr; + } $result[] = [ 'server' => $srv['name'], 'server_type' => $srv['type'], @@ -173,6 +187,8 @@ function vv_fetch_plex_sessions(array $srv): array { 'pos_sec' => (int)($offset / 1000), 'dur_sec' => (int)($dur / 1000), 'is_tc' => $isTc, + 'height' => $plexH, + 'codec' => strtolower($media0['videoCodec'] ?? ''), ]; } return $result; diff --git a/Plugin/unraid/pages/monitor.php b/Plugin/unraid/pages/monitor.php index 0190676..ae2a41e 100644 --- a/Plugin/unraid/pages/monitor.php +++ b/Plugin/unraid/pages/monitor.php @@ -1461,6 +1461,42 @@ function vvRenderStreams() { ? `·${deviceBar}` : ''; + // Resolution summary — e.g. "2 4K 3 1080p 1 720p" + function vvResLabel(h) { + if (h >= 2160) return '4K'; + if (h >= 1080) return '1080p'; + if (h >= 720) return '720p'; + if (h >= 480) return '480p'; + return null; + } + const resCounts = {}; + sessions.forEach(s => { + const r = vvResLabel(s.height || 0); + if (r) resCounts[r] = (resCounts[r] || 0) + 1; + }); + const resOrder = ['4K', '1080p', '720p', '480p']; + const resBar = resOrder.filter(r => resCounts[r]) + .map(r => `${resCounts[r]} ${r}`) + .join(''); + const resSection = resBar ? `·${resBar}` : ''; + + // Codec summary — e.g. "4 H.264 2 HEVC" + function vvCodecLabel(c) { + if (!c) return null; + const m = { h264: 'H.264', hevc: 'HEVC', av1: 'AV1', vp9: 'VP9', mpeg4: 'MPEG-4', mpeg2video: 'MPEG-2' }; + return m[c] || c.toUpperCase(); + } + const codecCounts = {}; + sessions.forEach(s => { + const c = vvCodecLabel(s.codec || ''); + if (c) codecCounts[c] = (codecCounts[c] || 0) + 1; + }); + const codecBar = Object.entries(codecCounts) + .sort((a, b) => b[1] - a[1]) + .map(([c, n]) => `${n} ${c}`) + .join(''); + const codecSection = codecBar ? `·${codecBar}` : ''; + if (sessions.length === 0) { el.innerHTML = `
${badges}
` + '

Nothing playing

'; @@ -1520,7 +1556,7 @@ function vvRenderStreams() { ? `
+${sessions.length - 12} more not shown
` : ''; - el.innerHTML = `
${badges}${deviceSection}
+ el.innerHTML = `
${badges}${deviceSection}${resSection}${codecSection}
${sCols.map(vvStreamCol).join('')}
${overflow}`; }