diff --git a/libs/ui/playback/src/lib/html-video-player/html-video-player-diagnostics.ts b/libs/ui/playback/src/lib/html-video-player/html-video-player-diagnostics.ts
index 3d4ffa8bd..048176b95 100644
--- a/libs/ui/playback/src/lib/html-video-player/html-video-player-diagnostics.ts
+++ b/libs/ui/playback/src/lib/html-video-player/html-video-player-diagnostics.ts
@@ -7,6 +7,7 @@ import {
classifyMpegTsPlaybackIssue,
classifyUnsupportedHlsManifestCodecs,
createHlsPlaybackEvidence,
+ createMpegTsPlaybackEvidence,
createPlaybackSourceMetadata,
} from '../playback-diagnostics/playback-diagnostics.util';
@@ -69,12 +70,16 @@ export function emitFatalHlsPlaybackError(
export function emitMpegTsPlaybackError(
url: string,
- error: { type: string; details: string; info: unknown },
+ error: { type: unknown; details: unknown; info: unknown },
emitPlaybackIssue: (issue: PlaybackDiagnostic) => void
): void {
emitPlaybackIssue(
classifyMpegTsPlaybackIssue(
- error,
+ createMpegTsPlaybackEvidence(
+ error.type,
+ error.details,
+ error.info
+ ),
createHtml5SourceMetadata(url, 'video/mp2t')
)
);
diff --git a/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.sources.spec.ts b/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.sources.spec.ts
index 929772534..ac5f748d5 100644
--- a/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.sources.spec.ts
+++ b/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.sources.spec.ts
@@ -114,6 +114,52 @@ describe('HtmlVideoPlayerComponent shared controls sources', () => {
}
);
+ it('emits structured HTTP evidence for mpegts.js failures', () => {
+ mpegTsIsSupported.mockReturnValue(true);
+ const { component } = renderSharedControls(
+ HtmlVideoPlayerComponent,
+ fixtures,
+ {
+ channel: {
+ ...TEST_CHANNEL,
+ url: 'https://example.test/missing.ts',
+ },
+ }
+ );
+ const issues: unknown[] = [];
+ component.playbackIssue.subscribe((issue) => issues.push(issue));
+ const secret = 'html-mpegts-secret';
+
+ mpegTsInstances[0].emit(
+ 'error',
+ 'NetworkError',
+ 'HttpStatusCodeInvalid',
+ {
+ code: 404,
+ msg: `Not Found ${secret}`,
+ url: `https://provider.example/error?token=${secret}`,
+ }
+ );
+
+ expect(issues).toEqual([
+ expect.objectContaining({
+ code: 'network-error',
+ source: 'mpegts',
+ sourceUrl: 'https://example.test/missing.ts',
+ player: 'html5',
+ httpStatus: 404,
+ mpegTs: expect.objectContaining({
+ engineType: 'NetworkError',
+ engineDetails: 'HttpStatusCodeInvalid',
+ failure: 'http',
+ httpStatus: 404,
+ }),
+ externalFallbackRecommended: false,
+ }),
+ ]);
+ expect(JSON.stringify(issues)).not.toContain(secret);
+ });
+
it('owns one MPEG-TS source between media attachment and loading', () => {
mpegTsIsSupported.mockReturnValue(true);
const { component } = renderSharedControls(
diff --git a/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.spec-fixtures.ts b/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.spec-fixtures.ts
index 65bce6152..006f4d97b 100644
--- a/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.spec-fixtures.ts
+++ b/libs/ui/playback/src/lib/html-video-player/html-video-player.component.shared-controls.spec-fixtures.ts
@@ -93,10 +93,22 @@ export class MockHls {
}
export class MockMpegTsPlayer {
+ private readonly listeners = new Map<
+ string,
+ Set<(...args: unknown[]) => void>
+ >();
readonly attachMediaElement = jest.fn(() =>
lifecycle.push('mpegts:attachMedia')
);
- readonly on = jest.fn();
+ readonly on = jest.fn(
+ (event: string, listener: (...args: unknown[]) => void) => {
+ const listeners =
+ this.listeners.get(event) ??
+ new Set<(...args: unknown[]) => void>();
+ listeners.add(listener);
+ this.listeners.set(event, listeners);
+ }
+ );
readonly load = jest.fn(() => lifecycle.push('mpegts:load'));
readonly pause = jest.fn();
readonly unload = jest.fn();
@@ -106,6 +118,12 @@ export class MockMpegTsPlayer {
constructor() {
mpegTsInstances.push(this);
}
+
+ emit(event: string, ...args: unknown[]): void {
+ for (const listener of this.listeners.get(event) ?? []) {
+ listener(...args);
+ }
+ }
}
export const mpegTsCreatePlayer = jest.fn(() => new MockMpegTsPlayer());