Files
iptvnator/libs/playback/util/src/lib/diagnostics/shaka-playback-evidence.util.ts
T
d73bb7ca16 chore(deps): bump shaka-player from 5.2.4 to 5.2.12 (#1836)
* chore(deps): bump shaka-player from 5.2.4 to 5.2.12

Bumps [shaka-player](https://github.com/shaka-project/shaka-player) from 5.2.4 to 5.2.12.
- [Release notes](https://github.com/shaka-project/shaka-player/releases)
- [Changelog](https://github.com/shaka-project/shaka-player/blob/v5.2.12/CHANGELOG.md)
- [Commits](https://github.com/shaka-project/shaka-player/compare/v5.2.4...v5.2.12)

---
updated-dependencies:
- dependency-name: shaka-player
  dependency-version: 5.2.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* test(playback): accept the Shaka 5.2.12 error contract

5.2.12 keeps the public error severities, categories, codes and request
types of 5.2.4, so the version lock moves to v5.2.12 with the same
accepted contract.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: 4gray <fourgray@proton.me>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:00:33 +02:00

265 lines
8.2 KiB
TypeScript

import {
type ShakaPlaybackCategory as ShakaPlaybackCategoryValue,
type ShakaPlaybackDisposition,
type ShakaPlaybackEvidence,
type ShakaPlaybackFailure as ShakaPlaybackFailureValue,
type ShakaPlaybackStage as ShakaPlaybackStageValue,
ShakaPlaybackCategory,
ShakaPlaybackFailure,
ShakaPlaybackSeverity,
ShakaPlaybackStage,
ShakaPlaybackUnknownCode,
} from './playback-diagnostics.model';
import {
SHAKA_ERROR_CATEGORY,
SHAKA_ERROR_CODE,
SHAKA_ERROR_SEVERITY,
SHAKA_REQUEST_TYPE,
} from './shaka-error-contract';
import {
SHAKA_AMBIGUOUS_MANIFEST_CODES,
SHAKA_DRM_CODES,
SHAKA_LICENSE_STAGE_CODES,
SHAKA_MANIFEST_CODES,
SHAKA_MANIFEST_DRM_CODES,
SHAKA_MANIFEST_MEDIA_CODES,
SHAKA_MEDIA_CODES,
SHAKA_MEDIA_STAGE_CODES,
SHAKA_NESTED_HTTP_CODES,
SHAKA_NETWORK_CODES,
SHAKA_PUBLIC_CODES,
SHAKA_SEGMENT_STAGE_CODES,
} from './shaka-error-mapping';
import type { ShakaErrorLike } from './shaka-error.types';
export function createShakaPlaybackEvidence(
error: Partial<ShakaErrorLike> | null | undefined,
disposition: ShakaPlaybackDisposition
): ShakaPlaybackEvidence {
const category = getCategory(error?.category);
const engineCode = getEngineCode(error?.code);
const httpStatus = getHttpStatus(error);
const evidence: ShakaPlaybackEvidence = {
severity: getSeverity(error?.severity),
category,
engineCode,
disposition,
stage: getNetworkStage(error) ?? getStage(category, engineCode),
failure: getFailure(category, engineCode),
};
return httpStatus === undefined ? evidence : { ...evidence, httpStatus };
}
/** Public error.data request-type slots in Shaka 5.2.12; no URL inspection. */
function getNetworkStage(error: Partial<ShakaErrorLike> | null | undefined) {
if (
error?.category !== SHAKA_ERROR_CATEGORY.NETWORK ||
!Array.isArray(error.data)
)
return undefined;
const slot =
error.code === SHAKA_ERROR_CODE.BAD_HTTP_STATUS
? 4
: error.code === SHAKA_ERROR_CODE.HTTP_ERROR
? 2
: error.code === SHAKA_ERROR_CODE.TIMEOUT
? 1
: undefined;
const type = slot === undefined ? undefined : error.data?.[slot];
switch (type) {
case SHAKA_REQUEST_TYPE.MANIFEST:
return ShakaPlaybackStage.Manifest;
case SHAKA_REQUEST_TYPE.SEGMENT:
return ShakaPlaybackStage.Segment;
case SHAKA_REQUEST_TYPE.LICENSE:
return ShakaPlaybackStage.License;
default:
return undefined;
}
}
function getSeverity(value: unknown): ShakaPlaybackEvidence['severity'] {
if (value === SHAKA_ERROR_SEVERITY.RECOVERABLE) {
return ShakaPlaybackSeverity.Recoverable;
}
if (value === SHAKA_ERROR_SEVERITY.CRITICAL) {
return ShakaPlaybackSeverity.Critical;
}
return ShakaPlaybackSeverity.Unknown;
}
function getCategory(value: unknown): ShakaPlaybackCategoryValue {
switch (value) {
case SHAKA_ERROR_CATEGORY.NETWORK:
return ShakaPlaybackCategory.Network;
case SHAKA_ERROR_CATEGORY.TEXT:
return ShakaPlaybackCategory.Text;
case SHAKA_ERROR_CATEGORY.MEDIA:
return ShakaPlaybackCategory.Media;
case SHAKA_ERROR_CATEGORY.MANIFEST:
return ShakaPlaybackCategory.Manifest;
case SHAKA_ERROR_CATEGORY.STREAMING:
return ShakaPlaybackCategory.Streaming;
case SHAKA_ERROR_CATEGORY.DRM:
return ShakaPlaybackCategory.Drm;
case SHAKA_ERROR_CATEGORY.PLAYER:
return ShakaPlaybackCategory.Player;
case SHAKA_ERROR_CATEGORY.CAST:
return ShakaPlaybackCategory.Cast;
case SHAKA_ERROR_CATEGORY.STORAGE:
return ShakaPlaybackCategory.Storage;
case SHAKA_ERROR_CATEGORY.ADS:
return ShakaPlaybackCategory.Ads;
default:
return ShakaPlaybackCategory.Unknown;
}
}
function getEngineCode(value: unknown): ShakaPlaybackEvidence['engineCode'] {
return typeof value === 'number' &&
Number.isInteger(value) &&
SHAKA_PUBLIC_CODES.has(value)
? value
: ShakaPlaybackUnknownCode;
}
function getFailure(
category: ShakaPlaybackCategoryValue,
engineCode: ShakaPlaybackEvidence['engineCode']
): ShakaPlaybackFailureValue {
if (
category === ShakaPlaybackCategory.Network &&
typeof engineCode === 'number' &&
SHAKA_NETWORK_CODES.has(engineCode)
) {
return ShakaPlaybackFailure.Network;
}
if (
category === ShakaPlaybackCategory.Drm &&
typeof engineCode === 'number' &&
SHAKA_DRM_CODES.has(engineCode)
) {
return ShakaPlaybackFailure.Drm;
}
if (
category === ShakaPlaybackCategory.Media &&
typeof engineCode === 'number' &&
SHAKA_MEDIA_CODES.has(engineCode)
) {
return ShakaPlaybackFailure.Media;
}
if (
category === ShakaPlaybackCategory.Manifest &&
typeof engineCode === 'number'
) {
if (SHAKA_MANIFEST_DRM_CODES.has(engineCode)) {
return ShakaPlaybackFailure.Drm;
}
if (SHAKA_MANIFEST_MEDIA_CODES.has(engineCode)) {
return ShakaPlaybackFailure.Media;
}
if (
SHAKA_MANIFEST_CODES.has(engineCode) &&
!SHAKA_AMBIGUOUS_MANIFEST_CODES.has(engineCode)
) {
return ShakaPlaybackFailure.Manifest;
}
}
return ShakaPlaybackFailure.Unknown;
}
function getStage(
category: ShakaPlaybackCategoryValue,
engineCode: ShakaPlaybackEvidence['engineCode']
): ShakaPlaybackStageValue {
if (typeof engineCode !== 'number') {
return ShakaPlaybackStage.Unknown;
}
if (
category === ShakaPlaybackCategory.Manifest &&
SHAKA_MANIFEST_CODES.has(engineCode)
) {
return ShakaPlaybackStage.Manifest;
}
if (
(category === ShakaPlaybackCategory.Network &&
engineCode === SHAKA_ERROR_CODE.SEGMENT_MISSING) ||
(category === ShakaPlaybackCategory.Media &&
SHAKA_SEGMENT_STAGE_CODES.has(engineCode))
) {
return ShakaPlaybackStage.Segment;
}
if (
category === ShakaPlaybackCategory.Media &&
SHAKA_MEDIA_STAGE_CODES.has(engineCode)
) {
return ShakaPlaybackStage.Media;
}
if (
category === ShakaPlaybackCategory.Drm &&
SHAKA_LICENSE_STAGE_CODES.has(engineCode)
) {
return ShakaPlaybackStage.License;
}
return ShakaPlaybackStage.Unknown;
}
function getHttpStatus(
error: Partial<ShakaErrorLike> | null | undefined
): number | undefined {
if (
error?.category === SHAKA_ERROR_CATEGORY.NETWORK &&
error.code === SHAKA_ERROR_CODE.BAD_HTTP_STATUS
) {
return asHttpStatus(error.data?.[1]);
}
if (
error?.category !== SHAKA_ERROR_CATEGORY.DRM ||
typeof error.code !== 'number' ||
!SHAKA_NESTED_HTTP_CODES.has(error.code)
) {
return undefined;
}
const nested = asShakaErrorData(error.data?.[0]);
return nested?.category === SHAKA_ERROR_CATEGORY.NETWORK &&
nested.code === SHAKA_ERROR_CODE.BAD_HTTP_STATUS
? asHttpStatus(nested.data?.[1])
: undefined;
}
function asShakaErrorData(value: unknown): Partial<ShakaErrorLike> | undefined {
if (!value || typeof value !== 'object') {
return undefined;
}
const candidate = value as {
readonly severity?: unknown;
readonly category?: unknown;
readonly code?: unknown;
readonly data?: unknown;
};
return {
severity:
typeof candidate.severity === 'number'
? candidate.severity
: undefined,
category:
typeof candidate.category === 'number'
? candidate.category
: undefined,
code: typeof candidate.code === 'number' ? candidate.code : undefined,
data: Array.isArray(candidate.data) ? candidate.data : undefined,
};
}
function asHttpStatus(value: unknown): number | undefined {
return typeof value === 'number' &&
Number.isInteger(value) &&
value >= 100 &&
value <= 599
? value
: undefined;
}