mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
124 lines
4.2 KiB
TypeScript
124 lines
4.2 KiB
TypeScript
import type {
|
|
PlaybackDiagnostic,
|
|
PlaybackDiagnosticCode,
|
|
PlaybackSourceMetadata,
|
|
ShakaPlaybackDisposition,
|
|
ShakaPlaybackEvidence,
|
|
} from './playback-diagnostics.model';
|
|
import {
|
|
PlaybackDiagnosticCode as DiagnosticCode,
|
|
PlaybackDiagnosticSource as DiagnosticSource,
|
|
ShakaPlaybackCategory,
|
|
ShakaPlaybackDisposition as ShakaDisposition,
|
|
ShakaPlaybackFailure,
|
|
PlaybackRuntimeSupport,
|
|
} from './playback-diagnostics.model';
|
|
import { createPlaybackDiagnostic } from './playback-diagnostics.util';
|
|
import { SHAKA_ERROR_CODE } from './shaka-error-contract';
|
|
import { createShakaPlaybackEvidence } from './shaka-playback-evidence.util';
|
|
import type { ShakaErrorLike } from './shaka-error.types';
|
|
import { getPlaybackDrmSystem } from './playback-stream-metadata';
|
|
|
|
export {
|
|
SHAKA_DIAGNOSTIC_VERSION,
|
|
SHAKA_ERROR_CATEGORY,
|
|
SHAKA_ERROR_CODE,
|
|
SHAKA_ERROR_SEVERITY,
|
|
} from './shaka-error-contract';
|
|
export { createShakaPlaybackEvidence } from './shaka-playback-evidence.util';
|
|
|
|
const MEDIA_DECODE_CODES = new Set<number>([
|
|
SHAKA_ERROR_CODE.MEDIA_SOURCE_OPERATION_FAILED,
|
|
SHAKA_ERROR_CODE.MEDIA_SOURCE_OPERATION_THREW,
|
|
SHAKA_ERROR_CODE.VIDEO_ERROR,
|
|
]);
|
|
|
|
export function classifyShakaPlaybackIssue(
|
|
error: Partial<ShakaErrorLike> | null | undefined,
|
|
metadata: PlaybackSourceMetadata,
|
|
disposition: ShakaPlaybackDisposition
|
|
): PlaybackDiagnostic | null {
|
|
const evidence = createShakaPlaybackEvidence(error, disposition);
|
|
if (evidence.disposition === ShakaDisposition.Recoverable) {
|
|
return null;
|
|
}
|
|
|
|
return createPlaybackDiagnostic({
|
|
code: getDiagnosticCode(evidence),
|
|
source: DiagnosticSource.Shaka,
|
|
metadata,
|
|
httpStatus: evidence.httpStatus,
|
|
shaka: evidence,
|
|
});
|
|
}
|
|
|
|
function getDiagnosticCode(
|
|
evidence: ShakaPlaybackEvidence
|
|
): PlaybackDiagnosticCode {
|
|
if (evidence.failure === ShakaPlaybackFailure.Network) {
|
|
return DiagnosticCode.NetworkError;
|
|
}
|
|
if (evidence.failure === ShakaPlaybackFailure.Drm) {
|
|
return DiagnosticCode.DrmOrEncryption;
|
|
}
|
|
if (
|
|
evidence.category === ShakaPlaybackCategory.Manifest &&
|
|
evidence.engineCode === SHAKA_ERROR_CODE.DASH_UNSUPPORTED_CONTAINER
|
|
) {
|
|
return DiagnosticCode.UnsupportedContainer;
|
|
}
|
|
if (
|
|
evidence.category === ShakaPlaybackCategory.Media &&
|
|
typeof evidence.engineCode === 'number' &&
|
|
MEDIA_DECODE_CODES.has(evidence.engineCode)
|
|
) {
|
|
return DiagnosticCode.MediaDecodeError;
|
|
}
|
|
return DiagnosticCode.UnknownPlaybackError;
|
|
}
|
|
|
|
/**
|
|
* Diagnostic for `.mpd` channels that declare a DRM system the app cannot
|
|
* handle. Provider-supplied license strings are intentionally not retained.
|
|
*/
|
|
export function createUnsupportedDrmDiagnostic(
|
|
licenseType: string,
|
|
metadata: PlaybackSourceMetadata
|
|
): PlaybackDiagnostic {
|
|
const system = getPlaybackDrmSystem(licenseType);
|
|
return createPlaybackDiagnostic({
|
|
code: DiagnosticCode.DrmOrEncryption,
|
|
source: DiagnosticSource.Shaka,
|
|
metadata: system ? { ...metadata, drmSystems: [system] } : metadata,
|
|
details: 'Unsupported DRM license configuration',
|
|
runtimeSupport: PlaybackRuntimeSupport.DrmConfigurationUnsupported,
|
|
});
|
|
}
|
|
|
|
/** Exact app-owned evidence for Shaka's browser-support preflight. */
|
|
export function createShakaBrowserUnsupportedDiagnostic(
|
|
metadata: PlaybackSourceMetadata
|
|
): PlaybackDiagnostic {
|
|
return createPlaybackDiagnostic({
|
|
code: DiagnosticCode.UnknownPlaybackError,
|
|
source: DiagnosticSource.Shaka,
|
|
metadata,
|
|
runtimeSupport: PlaybackRuntimeSupport.ShakaBrowserUnsupported,
|
|
shaka: createShakaPlaybackEvidence(null, ShakaDisposition.Terminal),
|
|
});
|
|
}
|
|
|
|
/** Narrows an unknown rejection to a Shaka-error-like shape, if it is one. */
|
|
export function asShakaError(error: unknown): Partial<ShakaErrorLike> | null {
|
|
if (!error || typeof error !== 'object') {
|
|
return null;
|
|
}
|
|
|
|
const candidate = error as Partial<ShakaErrorLike>;
|
|
return typeof candidate.code === 'number' ||
|
|
typeof candidate.category === 'number' ||
|
|
typeof candidate.severity === 'number'
|
|
? candidate
|
|
: null;
|
|
}
|