Files
iptvnator/libs/playback/util/src/lib/playback-recommendation.model.ts
T
4gray fd96b85c19 feat(playback): recommend recovery actions (#1374)
* docs(playback): design recovery recommendations

* docs(playback): plan recovery recommendations

* refactor(playback): extract diagnostic utilities

* feat(playback): define recovery recommendation contracts

* feat(playback): rank recovery recommendations

* feat(playback): track session recovery attempts

* feat(playback): identify content recovery sessions

* feat(ui): add ranked playback diagnostic panel

* feat(playback): switch temporarily to recommended players

* test(playback): cover temporary player recommendation

* test(playback): verify recommendation capability guards

* docs(playback): document recovery recommendations

* fix(playback): keep recovery keys credential-free

* fix(playback): remove derived tracking ownership

* fix(playback): preserve distinct recovery fallbacks

* fix(playback): reset resume for new sources

* fix(playback): preserve desktop recovery guidance

* docs(playback): clarify recovery policy exceptions

* fix(playback): reject stale progress updates

* fix(playback): keep protected recovery guidance neutral

* test(playback): cover stale progress output

* fix(playback): neutralize protected diagnostic copy

* fix(playback): harden runtime guidance ownership

* fix(playback): stabilize recovery application ownership

* fix(ci): classify playback util coverage

* fix(e2e): preserve playback fixture bytes
2026-08-08 01:04:39 +02:00

96 lines
3.0 KiB
TypeScript

import type {
ExternalPlayerName,
} from '@iptvnator/shared/interfaces';
import type {
InlinePlaybackPlayer,
PlaybackDiagnostic,
} from './diagnostics/playback-diagnostics.model';
export const PlaybackRecommendationReason = {
RetryTransientFailure: 'retry-transient-failure',
RetryUnknownFailure: 'retry-unknown-failure',
AlternativeSourceAvailable: 'alternative-source-available',
DifferentEngineFamily: 'different-engine-family',
ExternalCodecOrContainerSupport: 'external-codec-or-container-support',
ExternalBrowserAccess: 'external-browser-access',
CompatibleDrmPath: 'compatible-drm-path',
} as const;
export type PlaybackRecommendationReason =
(typeof PlaybackRecommendationReason)[keyof typeof PlaybackRecommendationReason];
export type PlaybackRecommendationPriority = 'primary' | 'secondary';
export type PlaybackRecommendationTarget =
| InlinePlaybackPlayer
| ExternalPlayerName;
export const PlaybackSourceKind = {
Hls: 'hls',
MpegTs: 'mpegts',
Dash: 'dash',
Native: 'native',
Unknown: 'unknown',
} as const;
export type PlaybackSourceKind =
(typeof PlaybackSourceKind)[keyof typeof PlaybackSourceKind];
export const PlaybackEngineFamily = {
Vhs: 'vhs',
HlsJs: 'hls.js',
MpegTsJs: 'mpegts.js',
Shaka: 'shaka',
NativeMedia: 'native-media',
} as const;
export type PlaybackEngineFamily =
(typeof PlaybackEngineFamily)[keyof typeof PlaybackEngineFamily];
export type PlaybackTargetCapability =
| {
readonly kind: 'inline';
readonly target: InlinePlaybackPlayer;
readonly available: boolean;
readonly engineFamily: PlaybackEngineFamily | null;
}
| {
readonly kind: 'external';
readonly target: ExternalPlayerName;
readonly available: boolean;
};
export interface PlaybackRecommendationSourceContext {
readonly kind: PlaybackSourceKind;
readonly isLive: boolean;
readonly drm: 'none' | 'untransferable';
readonly externalTransferable: boolean;
}
export interface PlaybackRecommendationContext {
readonly diagnostic: PlaybackDiagnostic;
readonly activeTarget: PlaybackRecommendationTarget;
readonly attemptedTargets: ReadonlySet<PlaybackRecommendationTarget>;
readonly targetCapabilities: readonly PlaybackTargetCapability[];
readonly source: PlaybackRecommendationSourceContext;
readonly alternativeSourceCount: number;
}
export type PlaybackRecommendation =
| {
readonly action: 'retry';
readonly reason: PlaybackRecommendationReason;
readonly priority: PlaybackRecommendationPriority;
}
| {
readonly action: 'alternative-source';
readonly reason: PlaybackRecommendationReason;
readonly priority: PlaybackRecommendationPriority;
}
| {
readonly action: 'player';
readonly target: PlaybackRecommendationTarget;
readonly reason: PlaybackRecommendationReason;
readonly priority: PlaybackRecommendationPriority;
};