From f6328bc873ef757e9a9408fb2ab95b1502474c5a Mon Sep 17 00:00:00 2001 From: 4gray Date: Tue, 4 Aug 2026 20:04:30 +0200 Subject: [PATCH] fix(playback): neutralize protected diagnostic copy --- apps/web/src/assets/i18n/ar.json | 4 +- apps/web/src/assets/i18n/ary.json | 4 +- apps/web/src/assets/i18n/by.json | 4 +- apps/web/src/assets/i18n/de.json | 4 +- apps/web/src/assets/i18n/el.json | 4 +- apps/web/src/assets/i18n/en.json | 4 +- apps/web/src/assets/i18n/es.json | 4 +- apps/web/src/assets/i18n/fr.json | 4 +- apps/web/src/assets/i18n/hu.json | 4 +- apps/web/src/assets/i18n/it.json | 4 +- apps/web/src/assets/i18n/ja.json | 4 +- apps/web/src/assets/i18n/ko.json | 4 +- apps/web/src/assets/i18n/nl.json | 4 +- apps/web/src/assets/i18n/pl.json | 4 +- apps/web/src/assets/i18n/pt.json | 4 +- apps/web/src/assets/i18n/ru.json | 4 +- apps/web/src/assets/i18n/tr.json | 4 +- apps/web/src/assets/i18n/zh.json | 4 +- apps/web/src/assets/i18n/zhtw.json | 4 +- .../playback-diagnostic-view.util.spec.ts | 129 ++++++++++++------ .../playback-diagnostic-view.util.ts | 15 +- .../web-player-view.component.spec.ts | 70 +++++----- 22 files changed, 176 insertions(+), 114 deletions(-) diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json index 51fbb71dd..0502c49da 100644 --- a/apps/web/src/assets/i18n/ar.json +++ b/apps/web/src/assets/i18n/ar.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json index 5013aff40..581fcfc72 100644 --- a/apps/web/src/assets/i18n/ary.json +++ b/apps/web/src/assets/i18n/ary.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json index d58c9a6fb..84d57fdd6 100644 --- a/apps/web/src/assets/i18n/by.json +++ b/apps/web/src/assets/i18n/by.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json index 3048c6f9f..ebf158524 100644 --- a/apps/web/src/assets/i18n/de.json +++ b/apps/web/src/assets/i18n/de.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json index 99fca591f..a7b2a8b99 100644 --- a/apps/web/src/assets/i18n/el.json +++ b/apps/web/src/assets/i18n/el.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json index ce788e57d..a5754aa74 100644 --- a/apps/web/src/assets/i18n/en.json +++ b/apps/web/src/assets/i18n/en.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json index 729cf98cf..baad2e909 100644 --- a/apps/web/src/assets/i18n/es.json +++ b/apps/web/src/assets/i18n/es.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json index bbac35b49..ecf59f1b3 100644 --- a/apps/web/src/assets/i18n/fr.json +++ b/apps/web/src/assets/i18n/fr.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/hu.json b/apps/web/src/assets/i18n/hu.json index 50f9bf2fa..cadfbb300 100644 --- a/apps/web/src/assets/i18n/hu.json +++ b/apps/web/src/assets/i18n/hu.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "A böngészőben működő lejátszó nem tudott hozzáférni ehhez az adatfolyamhoz", "DESCRIPTION": "A kérést CORS-korlátozás, vegyes tartalom, illetve a szolgáltató fejléc- vagy proxykorlátozásai akadályozhatják. Az MPV vagy a VLC gyakran képes megkerülni a böngészőben működő lejátszó hozzáférési korlátait.", - "PWA_DESCRIPTION": "A kérést CORS-korlátozás, vegyes tartalom, illetve a szolgáltató fejléc- vagy proxykorlátozásai akadályozhatják. A PWA nem tud közvetlenül külső lejátszót indítani; válassza az Adatfolyam URL-címének másolása műveletet, majd nyissa meg kézzel MPV-ben, VLC-ben, IINA-ban vagy más lejátszóban.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "A kérést CORS-korlátozás, vegyes tartalom, illetve a szolgáltató fejléc- vagy proxykorlátozásai akadályozhatják. A PWA nem tud közvetlenül külső lejátszót indítani; válassza az Adatfolyam URL-címének másolása műveletet, majd nyissa meg kézzel MPV-ben, VLC-ben, IINA-ban vagy más lejátszóban." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "Az adatfolyam titkosított vagy DRM-védelemmel ellátott lehet", "DESCRIPTION": "A böngészőben működő lejátszó a jelzett titkosítási vagy kulcshiba miatt nem tudja folytatni a lejátszást. Ha a szolgáltató DRM-védelmet alkalmaz, a külső lejátszás is sikertelen lehet." diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json index 0f54e8ba0..c3b25fc7b 100644 --- a/apps/web/src/assets/i18n/it.json +++ b/apps/web/src/assets/i18n/it.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json index a947ebaed..3734536b3 100644 --- a/apps/web/src/assets/i18n/ja.json +++ b/apps/web/src/assets/i18n/ja.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index d596d3781..6653602ad 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json index dda1694d0..4f0b05448 100644 --- a/apps/web/src/assets/i18n/nl.json +++ b/apps/web/src/assets/i18n/nl.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json index fcd7ee858..a3165f818 100644 --- a/apps/web/src/assets/i18n/pl.json +++ b/apps/web/src/assets/i18n/pl.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json index b03e403de..34ce3e6e3 100644 --- a/apps/web/src/assets/i18n/pt.json +++ b/apps/web/src/assets/i18n/pt.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json index a86a86e00..f95a46827 100644 --- a/apps/web/src/assets/i18n/ru.json +++ b/apps/web/src/assets/i18n/ru.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "Браузерный плеер не получил доступ к потоку", "DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. MPV или VLC часто обходят такие ограничения браузерного плеера.", - "PWA_DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. PWA не может запускать внешние плееры напрямую: нажмите «Скопировать URL потока» и откройте его вручную в MPV, VLC, IINA или другом плеере.", - "UNTRANSFERABLE_DESCRIPTION": "Для этого защищённого потока требуются настройки воспроизведения, которые нельзя передать вместе с URL-адресом потока." + "PWA_DESCRIPTION": "Запрос может быть заблокирован CORS, mixed content или требованиями провайдера/прокси к заголовкам. PWA не может запускать внешние плееры напрямую: нажмите «Скопировать URL потока» и откройте его вручную в MPV, VLC, IINA или другом плеере." }, + "UNTRANSFERABLE_DESCRIPTION": "Для этого защищённого потока требуются настройки воспроизведения, которые нельзя передать вместе с URL-адресом потока.", "DRM_OR_ENCRYPTION": { "TITLE": "Поток может быть зашифрован или защищен DRM", "DESCRIPTION": "Браузерный плеер не может продолжить из-за ошибки ключа или шифрования. Внешний плеер тоже может не помочь, если требуется DRM провайдера." diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json index 5b7bc4c7c..14df41536 100644 --- a/apps/web/src/assets/i18n/tr.json +++ b/apps/web/src/assets/i18n/tr.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json index f44d6187e..983395365 100644 --- a/apps/web/src/assets/i18n/zh.json +++ b/apps/web/src/assets/i18n/zh.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json index 516b009c9..09cfd812f 100644 --- a/apps/web/src/assets/i18n/zhtw.json +++ b/apps/web/src/assets/i18n/zhtw.json @@ -549,9 +549,9 @@ "BROWSER_ACCESS_ERROR": { "TITLE": "The browser player could not access this stream", "DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. MPV or VLC can often bypass browser-player access limits.", - "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player.", - "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL." + "PWA_DESCRIPTION": "The request may be blocked by CORS, mixed content, or provider header/proxy restrictions. The PWA cannot launch external players directly; use the Copy stream URL action and open it manually in MPV, VLC, IINA, or another player." }, + "UNTRANSFERABLE_DESCRIPTION": "This protected stream requires playback configuration that cannot be transferred with the stream URL.", "DRM_OR_ENCRYPTION": { "TITLE": "This stream may be encrypted or DRM-protected", "DESCRIPTION": "The browser player cannot continue with the reported encryption/key error. External playback may still fail if provider DRM is required." diff --git a/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.spec.ts b/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.spec.ts index c933644a3..c2aff28e2 100644 --- a/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.spec.ts +++ b/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.spec.ts @@ -43,50 +43,97 @@ describe('playback diagnostic view formatters', () => { ); }); - it.each([ + describe.each([ { - runtime: 'desktop', - supportsManagedExternalPlayers: true, - externallyTransferable: true, - expected: - 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.DESCRIPTION', - }, - { - runtime: 'PWA', - supportsManagedExternalPlayers: false, - externallyTransferable: true, - expected: - 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.PWA_DESCRIPTION', - }, - { - runtime: 'desktop with protected playback', - supportsManagedExternalPlayers: true, - externallyTransferable: false, - expected: - 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.UNTRANSFERABLE_DESCRIPTION', - }, - { - runtime: 'PWA with protected playback', - supportsManagedExternalPlayers: false, - externallyTransferable: false, - expected: - 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.UNTRANSFERABLE_DESCRIPTION', - }, - ])('uses $runtime browser-access copy', ({ - supportsManagedExternalPlayers, - externallyTransferable, - expected, - }) => { - const browserIssue: PlaybackDiagnostic = { - ...issue, + diagnostic: 'browser access', code: PlaybackDiagnosticCode.BrowserAccessError, - }; + desktopKey: + 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.DESCRIPTION', + pwaKey: 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.PWA_DESCRIPTION', + }, + { + diagnostic: 'unsupported codec', + code: PlaybackDiagnosticCode.UnsupportedCodec, + desktopKey: 'PLAYBACK_DIAGNOSTICS.UNSUPPORTED_CODEC.DESCRIPTION', + pwaKey: 'PLAYBACK_DIAGNOSTICS.UNSUPPORTED_CODEC.DESCRIPTION', + }, + { + diagnostic: 'unsupported container', + code: PlaybackDiagnosticCode.UnsupportedContainer, + desktopKey: + 'PLAYBACK_DIAGNOSTICS.UNSUPPORTED_CONTAINER.DESCRIPTION', + pwaKey: + 'PLAYBACK_DIAGNOSTICS.UNSUPPORTED_CONTAINER.DESCRIPTION', + }, + { + diagnostic: 'media decode', + code: PlaybackDiagnosticCode.MediaDecodeError, + desktopKey: 'PLAYBACK_DIAGNOSTICS.MEDIA_DECODE_ERROR.DESCRIPTION', + pwaKey: 'PLAYBACK_DIAGNOSTICS.MEDIA_DECODE_ERROR.DESCRIPTION', + }, + ])('$diagnostic description', ({ code, desktopKey, pwaKey }) => { + const diagnosticIssue: PlaybackDiagnostic = { ...issue, code }; + + it.each([ + { + runtime: 'desktop', + supportsManagedExternalPlayers: true, + expected: desktopKey, + }, + { + runtime: 'PWA', + supportsManagedExternalPlayers: false, + expected: pwaKey, + }, + ])('preserves transferable $runtime copy', ({ + supportsManagedExternalPlayers, + expected, + }) => { + expect( + getDiagnosticDescriptionKey( + diagnosticIssue, + supportsManagedExternalPlayers, + true + ) + ).toBe(expected); + }); + + it.each([ + ['desktop', true], + ['PWA', false], + ])( + 'uses neutral protected copy in the %s runtime', + (_runtime, supportsManagedExternalPlayers) => { + expect( + getDiagnosticDescriptionKey( + diagnosticIssue, + supportsManagedExternalPlayers, + false + ) + ).toBe('PLAYBACK_DIAGNOSTICS.UNTRANSFERABLE_DESCRIPTION'); + } + ); + }); + + it.each([ + [ + 'network', + PlaybackDiagnosticCode.NetworkError, + 'PLAYBACK_DIAGNOSTICS.NETWORK_ERROR.DESCRIPTION', + ], + [ + 'unknown', + PlaybackDiagnosticCode.UnknownPlaybackError, + 'PLAYBACK_DIAGNOSTICS.UNKNOWN_PLAYBACK_ERROR.DESCRIPTION', + ], + [ + 'DRM or encryption', + PlaybackDiagnosticCode.DrmOrEncryption, + 'PLAYBACK_DIAGNOSTICS.DRM_OR_ENCRYPTION.DESCRIPTION', + ], + ])('preserves neutral %s copy for protected playback', (_label, code, expected) => { expect( - getDiagnosticDescriptionKey( - browserIssue, - supportsManagedExternalPlayers, - externallyTransferable - ) + getDiagnosticDescriptionKey({ ...issue, code }, true, false) ).toBe(expected); }); }); diff --git a/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.ts b/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.ts index 23384cacf..9afebe81e 100644 --- a/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.ts +++ b/libs/ui/playback/src/lib/playback-diagnostic-panel/playback-diagnostic-view.util.ts @@ -4,6 +4,15 @@ import { getLikelyBrowserUnsupportedCodecLabels, } from '@iptvnator/playback/util'; +const UNTRANSFERABLE_EXTERNAL_RECOVERY_COPY_CODES: ReadonlySet< + PlaybackDiagnostic['code'] +> = new Set([ + PlaybackDiagnosticCode.BrowserAccessError, + PlaybackDiagnosticCode.UnsupportedCodec, + PlaybackDiagnosticCode.UnsupportedContainer, + PlaybackDiagnosticCode.MediaDecodeError, +]); + export type PlaybackDiagnosticDetail = { readonly labelKey: string; readonly value: string; @@ -19,10 +28,10 @@ export function getDiagnosticDescriptionKey( playbackExternallyTransferable: boolean ): string { if ( - issue.code === PlaybackDiagnosticCode.BrowserAccessError && - !playbackExternallyTransferable + !playbackExternallyTransferable && + UNTRANSFERABLE_EXTERNAL_RECOVERY_COPY_CODES.has(issue.code) ) { - return 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.UNTRANSFERABLE_DESCRIPTION'; + return 'PLAYBACK_DIAGNOSTICS.UNTRANSFERABLE_DESCRIPTION'; } if ( diff --git a/libs/ui/playback/src/lib/web-player-view/web-player-view.component.spec.ts b/libs/ui/playback/src/lib/web-player-view/web-player-view.component.spec.ts index 89e09e84d..76575d748 100644 --- a/libs/ui/playback/src/lib/web-player-view/web-player-view.component.spec.ts +++ b/libs/ui/playback/src/lib/web-player-view/web-player-view.component.spec.ts @@ -328,43 +328,49 @@ describe('WebPlayerViewComponent', () => { ); }); - it('uses neutral browser-access guidance when DRM cannot be transferred', () => { - runtimeCapabilities.supportsManagedExternalPlayers = true; - fixture.componentRef.setInput('playback', { - streamUrl: 'https://provider.example/protected.mpd', - title: 'Protected stream', - drm: { - licenseType: 'clearkey', - supported: true, - clearKeys: { - '00112233445566778899aabbccddeeff': - 'ffeeddccbbaa99887766554433221100', + it.each([ + ['browser-access', createBrowserAccessDiagnostic], + ['unsupported-codec', createUnsupportedCodecDiagnostic], + ])( + 'uses neutral %s guidance when ClearKey playback cannot be transferred', + (_diagnostic, createDiagnostic) => { + runtimeCapabilities.supportsManagedExternalPlayers = true; + fixture.componentRef.setInput('playback', { + streamUrl: 'https://provider.example/protected.mpd', + title: 'Protected stream', + drm: { + licenseType: 'clearkey', + supported: true, + clearKeys: { + '00112233445566778899aabbccddeeff': + 'ffeeddccbbaa99887766554433221100', + }, }, - }, - }); + }); - fixture.detectChanges(); - emitPlaybackIssue(createBrowserAccessDiagnostic()); - fixture.detectChanges(); + fixture.detectChanges(); + emitPlaybackIssue(createDiagnostic()); + fixture.detectChanges(); - const banner = fixture.debugElement.query( - By.css('[data-test-id="playback-diagnostic-banner"]') - ); + const banner = fixture.debugElement.query( + By.css('[data-test-id="playback-diagnostic-banner"]') + ); - expect(banner.nativeElement.textContent).toContain( - 'PLAYBACK_DIAGNOSTICS.UNTRANSFERABLE_FAILURE_TITLE' - ); - expect(banner.nativeElement.textContent).toContain( - 'PLAYBACK_DIAGNOSTICS.BROWSER_ACCESS_ERROR.UNTRANSFERABLE_DESCRIPTION' - ); - expect( - banner.query( - By.css( - '[data-test-id="playback-fallback-mpv"], [data-test-id="playback-fallback-vlc"]' + expect(banner.nativeElement.textContent).toContain( + 'PLAYBACK_DIAGNOSTICS.UNTRANSFERABLE_FAILURE_TITLE' + ); + expect(banner.nativeElement.textContent).toContain( + 'PLAYBACK_DIAGNOSTICS.UNTRANSFERABLE_DESCRIPTION' + ); + expect( + banner.query( + By.css( + '[data-test-id="playback-fallback-mpv"], [data-test-id="playback-fallback-vlc"]' + ) ) - ) - ).toBeNull(); - }); + ).toBeNull(); + } + ); it('renders only sanitized structured HLS evidence in technical details', () => { const issue = createStructuredHlsDiagnostic();