fix(playback): render structured mpegts evidence

This commit is contained in:
4gray committed 2026-08-01 16:20:18 +02:00
1 parent dfd7ac84d4
commit ec6c016636
2 files changed
+74 -1

No files matched your search

@@ -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}`,
@@ -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,
};
}