diff --git a/libs/ui/playback/src/lib/web-player-view/web-player-view-diagnostics.utils.ts b/libs/ui/playback/src/lib/web-player-view/web-player-view-diagnostics.utils.ts index 08d536456..284ab8575 100644 --- a/libs/ui/playback/src/lib/web-player-view/web-player-view-diagnostics.utils.ts +++ b/libs/ui/playback/src/lib/web-player-view/web-player-view-diagnostics.utils.ts @@ -83,7 +83,7 @@ export function getDiagnosticDetails( { labelKey: 'PLAYBACK_DIAGNOSTICS.DETAIL_NATIVE_ERROR_MESSAGE', value: - issue.vhs || issue.shaka + issue.vhs || issue.mpegTs || issue.shaka ? '' : (issue.nativeErrorMessage ?? ''), }, @@ -95,6 +95,21 @@ export function getDiagnosticDetails( } function formatDiagnosticErrorDetails(issue: PlaybackDiagnostic): string { + if (issue.mpegTs) { + return [ + `stage=${issue.mpegTs.stage}`, + `failure=${issue.mpegTs.failure}`, + `type=${issue.mpegTs.engineType}`, + `details=${issue.mpegTs.engineDetails}`, + `disposition=${issue.mpegTs.disposition}`, + issue.mpegTs.httpStatus === undefined + ? '' + : `HTTP ${issue.mpegTs.httpStatus}`, + ] + .filter((value) => value.length > 0) + .join(' · '); + } + if (issue.shaka) { return [ `stage=${issue.shaka.stage}`, 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 8d550fb13..8c3eccb57 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 @@ -401,6 +401,37 @@ describe('WebPlayerViewComponent', () => { expect(renderedDetails).not.toContain('response body'); }); + it('renders only sanitized structured mpegts evidence in technical details', () => { + const issue = createStructuredMpegTsDiagnostic(); + + component.handlePlaybackIssue(issue); + fixture.detectChanges(); + + const details = component.getDiagnosticDetails(issue); + const renderedDetails = details.map(({ value }) => value).join(' '); + + expect(component.getDiagnosticMeta(issue)).toBe('HTTP 404'); + expect(details).toEqual( + expect.arrayContaining([ + { + labelKey: 'PLAYBACK_DIAGNOSTICS.DETAIL_SOURCE', + value: 'mpegts.js', + }, + { + labelKey: 'PLAYBACK_DIAGNOSTICS.DETAIL_ERROR_DETAILS', + value: + 'stage=loader · failure=http · type=NetworkError · ' + + 'details=HttpStatusCodeInvalid · ' + + 'disposition=terminal · HTTP 404', + }, + ]) + ); + expect(renderedDetails).not.toContain('mpegts-render-secret'); + expect(renderedDetails).not.toContain('provider.example'); + expect(renderedDetails).not.toContain('Authorization'); + expect(renderedDetails).not.toContain('response body'); + }); + it('keeps query-declared HLS streams on the HLS mime type', () => { const streamUrl = 'https://example.com/play?extension=m3u8&token=signed'; @@ -1038,3 +1069,30 @@ function createStructuredShakaDiagnostic(): PlaybackDiagnostic { externalFallbackRecommended: false, }; } + +function createStructuredMpegTsDiagnostic(): PlaybackDiagnostic { + return { + code: PlaybackDiagnosticCode.NetworkError, + source: PlaybackDiagnosticSource.MpegTs, + sourceUrl: + 'https://provider.example/live.ts?token=mpegts-render-secret', + container: 'ts', + mimeType: 'video/mp2t', + player: 'html5', + audioCodecs: [], + videoCodecs: [], + details: 'Authorization response body mpegts-render-secret', + nativeErrorMessage: + 'https://provider.example/error?token=mpegts-render-secret', + httpStatus: 404, + mpegTs: { + engineType: 'NetworkError', + engineDetails: 'HttpStatusCodeInvalid', + disposition: 'terminal', + stage: 'loader', + failure: 'http', + httpStatus: 404, + }, + externalFallbackRecommended: false, + }; +}