mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
build(spf): build26 from 45504a2b
This commit is contained in:
Vendored
+13
@@ -0,0 +1,13 @@
|
||||
//#region src/media/utils/cdn.d.ts
|
||||
/**
|
||||
* Derive a stable grouping key for the CDN a URL is served from. Synchronous and
|
||||
* pure (deliberately not a `resolve*` — no fetch). Consumers override the
|
||||
* default via the engine's `getCdnId` config (e.g. to key on Mux's `cdn=` query
|
||||
* param instead of the host); every CDN-identity site reads that same function
|
||||
* so keys stay comparable across `cdnPriority`, `failedCdns`, and the
|
||||
* track-switching constraint + scope.
|
||||
*/
|
||||
type GetCdnId = (url: string) => string;
|
||||
//#endregion
|
||||
export { GetCdnId };
|
||||
//# sourceMappingURL=cdn.d.ts.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cdn.d.ts","names":[],"sources":["../../../../src/media/utils/cdn.ts"],"mappings":";;;;;;;;;KAUY,YAAY"}
|
||||
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
//#region src/media/utils/cdn.ts
|
||||
/**
|
||||
* Default {@link GetCdnId}: the URL's origin (scheme + host + port); falls back
|
||||
* to the raw string when the URL can't be parsed, so the return value is always
|
||||
* a stable grouping key.
|
||||
*/
|
||||
function getCdnId(url) {
|
||||
try {
|
||||
return new URL(url).origin;
|
||||
} catch {
|
||||
return url;
|
||||
}
|
||||
}
|
||||
const CDN_TYPE_PRIORITY = {
|
||||
video: 0,
|
||||
audio: 1,
|
||||
text: 2
|
||||
};
|
||||
/**
|
||||
* The distinct CDNs a presentation's tracks are served from, ordered video CDNs
|
||||
* first, then audio, then text (manifest order within a type). The head is the
|
||||
* primary CDN — the one a sticky pick defaults to — and is always video-derived
|
||||
* when the source has video. Returns `[]` for an unresolved presentation with
|
||||
* no tracks.
|
||||
*
|
||||
* Redundant-stream sources list the same content on multiple hosts (e.g. Mux's
|
||||
* `?redundant_streams=true`), so each host contributes its own candidate tracks;
|
||||
* this collapses them to the set of CDNs across every track type. The CDN-id
|
||||
* derivation defaults to {@link getCdnId}; pass a consumer-configured `getId` to
|
||||
* key on something other than origin.
|
||||
*/
|
||||
function getOrderedCdnIds(presentation, getId = getCdnId) {
|
||||
const seen = /* @__PURE__ */ new Set();
|
||||
const ids = [];
|
||||
const selectionSets = [...presentation.selectionSets ?? []].sort((a, b) => CDN_TYPE_PRIORITY[a.type] - CDN_TYPE_PRIORITY[b.type]);
|
||||
for (const selectionSet of selectionSets) for (const switchingSet of selectionSet.switchingSets) for (const track of switchingSet.tracks) {
|
||||
const id = getId(track.url);
|
||||
if (seen.has(id)) continue;
|
||||
seen.add(id);
|
||||
ids.push(id);
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
/**
|
||||
* Add a CDN id to a failed-CDN list, preserving order and ignoring duplicates.
|
||||
* Idempotent: re-adding an already-present id returns the same array reference
|
||||
* (so a no-op trip doesn't churn the `failedCdns` signal). The failover trip in
|
||||
* `resolve-track` and the segment loaders feed this into `failedCdns` via `update`.
|
||||
*/
|
||||
function addFailedCdn(failed, cdn) {
|
||||
return failed?.includes(cdn) ? failed : [...failed ?? [], cdn];
|
||||
}
|
||||
//#endregion
|
||||
export { addFailedCdn, getCdnId, getOrderedCdnIds };
|
||||
|
||||
//# sourceMappingURL=cdn.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cdn.js","names":[],"sources":["../../../../src/media/utils/cdn.ts"],"sourcesContent":["import type { MaybeResolvedPresentation, TrackType } from '../types';\n\n/**\n * Derive a stable grouping key for the CDN a URL is served from. Synchronous and\n * pure (deliberately not a `resolve*` — no fetch). Consumers override the\n * default via the engine's `getCdnId` config (e.g. to key on Mux's `cdn=` query\n * param instead of the host); every CDN-identity site reads that same function\n * so keys stay comparable across `cdnPriority`, `failedCdns`, and the\n * track-switching constraint + scope.\n */\nexport type GetCdnId = (url: string) => string;\n\n/**\n * Default {@link GetCdnId}: the URL's origin (scheme + host + port); falls back\n * to the raw string when the URL can't be parsed, so the return value is always\n * a stable grouping key.\n */\nexport function getCdnId(url: string): string {\n try {\n return new URL(url).origin;\n } catch {\n return url;\n }\n}\n\n// Track-type priority for CDN ordering: video first, then audio, then text.\n// Selection sets are visited in this order so the head of the returned list is\n// always video-derived. `preferActiveCdn` anchors every track type to the\n// first CDN with surviving tracks (the head), so this makes \"the primary CDN\n// is the video CDN\" a guarantee of `getOrderedCdnIds` rather than a side effect\n// of the order tracks happen to be parsed in.\nconst CDN_TYPE_PRIORITY: Record<TrackType, number> = { video: 0, audio: 1, text: 2 };\n\n/**\n * The distinct CDNs a presentation's tracks are served from, ordered video CDNs\n * first, then audio, then text (manifest order within a type). The head is the\n * primary CDN — the one a sticky pick defaults to — and is always video-derived\n * when the source has video. Returns `[]` for an unresolved presentation with\n * no tracks.\n *\n * Redundant-stream sources list the same content on multiple hosts (e.g. Mux's\n * `?redundant_streams=true`), so each host contributes its own candidate tracks;\n * this collapses them to the set of CDNs across every track type. The CDN-id\n * derivation defaults to {@link getCdnId}; pass a consumer-configured `getId` to\n * key on something other than origin.\n */\nexport function getOrderedCdnIds(presentation: MaybeResolvedPresentation, getId: GetCdnId = getCdnId): string[] {\n const seen = new Set<string>();\n const ids: string[] = [];\n // Stable sort keeps manifest order among same-type selection sets.\n const selectionSets = [...(presentation.selectionSets ?? [])].sort(\n (a, b) => CDN_TYPE_PRIORITY[a.type] - CDN_TYPE_PRIORITY[b.type]\n );\n for (const selectionSet of selectionSets) {\n for (const switchingSet of selectionSet.switchingSets) {\n for (const track of switchingSet.tracks) {\n const id = getId(track.url);\n if (seen.has(id)) continue;\n seen.add(id);\n ids.push(id);\n }\n }\n }\n return ids;\n}\n\n/**\n * Add a CDN id to a failed-CDN list, preserving order and ignoring duplicates.\n * Idempotent: re-adding an already-present id returns the same array reference\n * (so a no-op trip doesn't churn the `failedCdns` signal). The failover trip in\n * `resolve-track` and the segment loaders feed this into `failedCdns` via `update`.\n */\nexport function addFailedCdn(failed: string[] | undefined, cdn: string): string[] {\n return failed?.includes(cdn) ? failed : [...(failed ?? []), cdn];\n}\n"],"mappings":";;;;;;AAiBA,SAAgB,SAAS,KAAqB;CAC5C,IAAI;EACF,OAAO,IAAI,IAAI,GAAG,CAAC,CAAC;CACtB,QAAQ;EACN,OAAO;CACT;AACF;AAQA,MAAM,oBAA+C;CAAE,OAAO;CAAG,OAAO;CAAG,MAAM;AAAE;;;;;;;;;;;;;;AAenF,SAAgB,iBAAiB,cAAyC,QAAkB,UAAoB;CAC9G,MAAM,uBAAO,IAAI,IAAY;CAC7B,MAAM,MAAgB,CAAC;CAEvB,MAAM,gBAAgB,CAAC,GAAI,aAAa,iBAAiB,CAAC,CAAE,CAAC,CAAC,MAC3D,GAAG,MAAM,kBAAkB,EAAE,QAAQ,kBAAkB,EAAE,KAC5D;CACA,KAAK,MAAM,gBAAgB,eACzB,KAAK,MAAM,gBAAgB,aAAa,eACtC,KAAK,MAAM,SAAS,aAAa,QAAQ;EACvC,MAAM,KAAK,MAAM,MAAM,GAAG;EAC1B,IAAI,KAAK,IAAI,EAAE,GAAG;EAClB,KAAK,IAAI,EAAE;EACX,IAAI,KAAK,EAAE;CACb;CAGJ,OAAO;AACT;;;;;;;AAQA,SAAgB,aAAa,QAA8B,KAAuB;CAChF,OAAO,QAAQ,SAAS,GAAG,IAAI,SAAS,CAAC,GAAI,UAAU,CAAC,GAAI,GAAG;AACjE"}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
//#region src/media/utils/preload.ts
|
||||
function isStandardPreload(value) {
|
||||
return value === "auto" || value === "metadata" || value === "none";
|
||||
}
|
||||
/**
|
||||
* Default `preload` value used as the fallback across behaviors
|
||||
* (`syncPreload`, `resolvePresentation`, `isBlockingPreload`). Matches the
|
||||
* `<video>`/`<audio>` element's implicit default.
|
||||
*/
|
||||
const DEFAULT_PRELOAD = "metadata";
|
||||
/**
|
||||
* True when the preload value blocks initial resolution / loading.
|
||||
* Falsy values (undefined, empty) fall back to `defaultPreload` (default
|
||||
* `DEFAULT_PRELOAD`); the resolved value blocks iff it is `'none'`.
|
||||
*/
|
||||
function isBlockingPreload(preload, defaultPreload = DEFAULT_PRELOAD) {
|
||||
return (preload || defaultPreload) === "none";
|
||||
}
|
||||
//#endregion
|
||||
export { DEFAULT_PRELOAD, isBlockingPreload, isStandardPreload };
|
||||
|
||||
//# sourceMappingURL=preload.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"preload.js","names":[],"sources":["../../../../src/media/utils/preload.ts"],"sourcesContent":["/**\n * The W3C-standard set of `<video>`/`<audio>` `preload` attribute values.\n * SPF allows extended values (e.g. `'canplay'`) on `state.preload`, which\n * are *not* reflected to the DOM — predicate below is the discriminator.\n */\nexport type StandardPreload = 'auto' | 'metadata' | 'none';\n\nexport function isStandardPreload(value: unknown): value is StandardPreload {\n return value === 'auto' || value === 'metadata' || value === 'none';\n}\n\n/**\n * Default `preload` value used as the fallback across behaviors\n * (`syncPreload`, `resolvePresentation`, `isBlockingPreload`). Matches the\n * `<video>`/`<audio>` element's implicit default.\n */\nexport const DEFAULT_PRELOAD = 'metadata';\n\n/**\n * True when the preload value blocks initial resolution / loading.\n * Falsy values (undefined, empty) fall back to `defaultPreload` (default\n * `DEFAULT_PRELOAD`); the resolved value blocks iff it is `'none'`.\n */\nexport function isBlockingPreload(\n preload: string | undefined,\n defaultPreload: StandardPreload = DEFAULT_PRELOAD\n): boolean {\n return (preload || defaultPreload) === 'none';\n}\n"],"mappings":";AAOA,SAAgB,kBAAkB,OAA0C;CAC1E,OAAO,UAAU,UAAU,UAAU,cAAc,UAAU;AAC/D;;;;;;AAOA,MAAa,kBAAkB;;;;;;AAO/B,SAAgB,kBACd,SACA,iBAAkC,iBACzB;CACT,QAAQ,WAAW,oBAAoB;AACzC"}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
import { isResolvedTrack } from "../types/index.js";
|
||||
//#region src/media/utils/track-selection.ts
|
||||
/**
|
||||
* Map track type to selected track ID property key in state.
|
||||
*/
|
||||
const SelectedTrackIdKeyByType = {
|
||||
video: "selectedVideoTrackId",
|
||||
audio: "selectedAudioTrackId",
|
||||
text: "selectedTextTrackId"
|
||||
};
|
||||
/**
|
||||
* Get selected track from state by type.
|
||||
* Returns properly typed track (partially or fully resolved) or undefined.
|
||||
* Type parameter T is inferred from the type argument.
|
||||
*
|
||||
* @example
|
||||
* const videoTrack = getSelectedTrack(state, 'video');
|
||||
* if (videoTrack && isResolvedTrack(videoTrack)) {
|
||||
* // videoTrack is VideoTrack
|
||||
* }
|
||||
*/
|
||||
function getSelectedTrack(state, type) {
|
||||
const { presentation } = state;
|
||||
if (!presentation?.selectionSets) return void 0;
|
||||
const trackId = state[SelectedTrackIdKeyByType[type]];
|
||||
return presentation.selectionSets.find(({ type: selectionSetType }) => selectionSetType === type)?.switchingSets[0]?.tracks.find(({ id }) => id === trackId);
|
||||
}
|
||||
/**
|
||||
* Returns the duration of the first resolved selected track, preferring
|
||||
* video over audio. A track is "resolved" once its media playlist has been
|
||||
* parsed (per {@link isResolvedTrack}). Returns `undefined` if neither
|
||||
* selected track is resolved.
|
||||
*/
|
||||
function getResolvedSelectedTrackDuration(state) {
|
||||
if (state.selectedVideoTrackId) {
|
||||
const video = getSelectedTrack(state, "video");
|
||||
if (video && isResolvedTrack(video)) return video.duration;
|
||||
}
|
||||
if (state.selectedAudioTrackId) {
|
||||
const audio = getSelectedTrack(state, "audio");
|
||||
if (audio && isResolvedTrack(audio)) return audio.duration;
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
export { SelectedTrackIdKeyByType, getResolvedSelectedTrackDuration, getSelectedTrack };
|
||||
|
||||
//# sourceMappingURL=track-selection.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"track-selection.js","names":[],"sources":["../../../../src/media/utils/track-selection.ts"],"sourcesContent":["import type {\n AudioTrack,\n MaybeResolvedPresentation,\n PartiallyResolvedAudioTrack,\n PartiallyResolvedTextTrack,\n PartiallyResolvedVideoTrack,\n TextTrack,\n TrackType,\n VideoTrack,\n} from '../types';\nimport { isResolvedTrack } from '../types';\n\n/**\n * State shape for track selection.\n * Minimal shape containing presentation and selected track IDs.\n */\nexport interface TrackSelectionState {\n presentation?: MaybeResolvedPresentation;\n selectedVideoTrackId?: string | undefined;\n selectedAudioTrackId?: string | undefined;\n selectedTextTrackId?: string | undefined;\n}\n\n/**\n * Map track type to selected track ID property key in state.\n */\nexport const SelectedTrackIdKeyByType = {\n video: 'selectedVideoTrackId',\n audio: 'selectedAudioTrackId',\n text: 'selectedTextTrackId',\n} as const;\n\n/**\n * Get selected track from state by type.\n * Returns properly typed track (partially or fully resolved) or undefined.\n * Type parameter T is inferred from the type argument.\n *\n * @example\n * const videoTrack = getSelectedTrack(state, 'video');\n * if (videoTrack && isResolvedTrack(videoTrack)) {\n * // videoTrack is VideoTrack\n * }\n */\nexport function getSelectedTrack<T extends TrackType>(\n state: TrackSelectionState,\n type: T\n): T extends 'video'\n ? PartiallyResolvedVideoTrack | VideoTrack | undefined\n : T extends 'audio'\n ? PartiallyResolvedAudioTrack | AudioTrack | undefined\n : T extends 'text'\n ? PartiallyResolvedTextTrack | TextTrack | undefined\n : never {\n const { presentation } = state;\n\n if (!presentation?.selectionSets) return undefined as any;\n\n // Get track ID based on type\n const trackIdKey = SelectedTrackIdKeyByType[type];\n const trackId = state[trackIdKey];\n return presentation.selectionSets\n .find(({ type: selectionSetType }) => selectionSetType === type)\n ?.switchingSets[0]?.tracks.find(({ id }) => id === trackId) as any;\n}\n\n/**\n * Returns the duration of the first resolved selected track, preferring\n * video over audio. A track is \"resolved\" once its media playlist has been\n * parsed (per {@link isResolvedTrack}). Returns `undefined` if neither\n * selected track is resolved.\n */\nexport function getResolvedSelectedTrackDuration(state: TrackSelectionState): number | undefined {\n if (state.selectedVideoTrackId) {\n const video = getSelectedTrack(state, 'video');\n if (video && isResolvedTrack(video)) return video.duration;\n }\n if (state.selectedAudioTrackId) {\n const audio = getSelectedTrack(state, 'audio');\n if (audio && isResolvedTrack(audio)) return audio.duration;\n }\n return undefined;\n}\n"],"mappings":";;;;;AA0BA,MAAa,2BAA2B;CACtC,OAAO;CACP,OAAO;CACP,MAAM;AACR;;;;;;;;;;;;AAaA,SAAgB,iBACd,OACA,MAOY;CACZ,MAAM,EAAE,iBAAiB;CAEzB,IAAI,CAAC,cAAc,eAAe,OAAO,KAAA;CAIzC,MAAM,UAAU,MADG,yBAAyB;CAE5C,OAAO,aAAa,cACjB,MAAM,EAAE,MAAM,uBAAuB,qBAAqB,IAAI,CAAC,EAC9D,cAAc,EAAE,EAAE,OAAO,MAAM,EAAE,SAAS,OAAO,OAAO;AAC9D;;;;;;;AAQA,SAAgB,iCAAiC,OAAgD;CAC/F,IAAI,MAAM,sBAAsB;EAC9B,MAAM,QAAQ,iBAAiB,OAAO,OAAO;EAC7C,IAAI,SAAS,gBAAgB,KAAK,GAAG,OAAO,MAAM;CACpD;CACA,IAAI,MAAM,sBAAsB;EAC9B,MAAM,QAAQ,iBAAiB,OAAO,OAAO;EAC7C,IAAI,SAAS,gBAAgB,KAAK,GAAG,OAAO,MAAM;CACpD;AAEF"}
|
||||
Vendored
+130
@@ -0,0 +1,130 @@
|
||||
import { isResolvedTrack } from "../types/index.js";
|
||||
//#region src/media/utils/tracks.ts
|
||||
/**
|
||||
* Get the tracks of the given type from a presentation's first switching set.
|
||||
*
|
||||
* Returns `[]` when the presentation is unresolved, when no selection set of
|
||||
* `type` exists, or when its first switching set is empty. Returned tracks may
|
||||
* be partially resolved (URL only) or fully resolved (with segments) — callers
|
||||
* narrow as needed.
|
||||
*
|
||||
* The "first switching set" assumption matches the rest of the codebase
|
||||
* (HLS typically has one switching set per type); multi-group / multi-period
|
||||
* support would generalize this.
|
||||
*/
|
||||
function getTracksByType(presentation, type) {
|
||||
return presentation.selectionSets?.find(({ type: t }) => t === type)?.switchingSets[0]?.tracks ?? [];
|
||||
}
|
||||
/**
|
||||
* Find a track of the given type and id within a presentation.
|
||||
*
|
||||
* Returns the matching track from the first switching set of the matching
|
||||
* selection set, or `undefined` if either is missing. The returned track may
|
||||
* be partially resolved (URL only) or fully resolved (with segments) — callers
|
||||
* narrow as needed.
|
||||
*/
|
||||
function findTrack(presentation, type, trackId) {
|
||||
return getTracksByType(presentation, type).find(({ id }) => id === trackId);
|
||||
}
|
||||
/**
|
||||
* Find a track by id across all selection sets in a presentation, without
|
||||
* knowing its type up front. Used when the caller has a track id obtained
|
||||
* from a downstream consumer (e.g. `SourceBufferActor.initTrackId`) and
|
||||
* needs to locate the corresponding track in the presentation.
|
||||
*
|
||||
* Track ids are unique within a presentation per the HLS spec; the first
|
||||
* match wins.
|
||||
*/
|
||||
function findTrackById(presentation, trackId) {
|
||||
for (const selectionSet of presentation.selectionSets ?? []) {
|
||||
const track = selectionSet.switchingSets[0]?.tracks.find(({ id }) => id === trackId);
|
||||
if (track) return track;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Find a text track of the given id within a presentation and narrow it to
|
||||
* the fully-resolved `TextTrack` shape (segments populated). Returns
|
||||
* `undefined` if no track matches the id, the matching track isn't a text
|
||||
* track, or it hasn't been resolved yet.
|
||||
*
|
||||
* The segments-non-empty check stays at the call site — a resolved track
|
||||
* with zero segments is a valid state, distinct from "ready to load."
|
||||
*/
|
||||
function findResolvedTextTrack(presentation, trackId) {
|
||||
if (!presentation || !trackId) return void 0;
|
||||
const track = findTrack(presentation, "text", trackId);
|
||||
if (track?.type !== "text" || !isResolvedTrack(track)) return void 0;
|
||||
return track;
|
||||
}
|
||||
function findResolvedVideoTrack(presentation, trackId) {
|
||||
if (!presentation || !trackId) return void 0;
|
||||
const track = findTrack(presentation, "video", trackId);
|
||||
if (track?.type !== "video" || !isResolvedTrack(track)) return void 0;
|
||||
return track;
|
||||
}
|
||||
function findResolvedAudioTrack(presentation, trackId) {
|
||||
if (!presentation || !trackId) return void 0;
|
||||
const track = findTrack(presentation, "audio", trackId);
|
||||
if (track?.type !== "audio" || !isResolvedTrack(track)) return void 0;
|
||||
return track;
|
||||
}
|
||||
/**
|
||||
* Whether a track carries a non-empty `codecs` array. Both partially-
|
||||
* resolved and fully-resolved tracks may carry codecs — they come from
|
||||
* the multivariant playlist's `EXT-X-STREAM-INF` line, not from the
|
||||
* per-type media playlist — so this works at either resolution stage.
|
||||
*
|
||||
* `TextTrack` doesn't declare a `codecs` field; the `'codecs' in track`
|
||||
* check narrows it out for the false branch.
|
||||
*/
|
||||
function hasCodecs(track) {
|
||||
return !!track && "codecs" in track && !!track.codecs?.length;
|
||||
}
|
||||
/**
|
||||
* Set `mimeType` on every track of one `type` (immutably). Used to propagate a
|
||||
* detected container across a type's renditions: an ABR ladder is the same
|
||||
* content at different bitrates, so one rendition's container holds for all of
|
||||
* them — capability probing + SourceBuffer setup then get the right MIME for the
|
||||
* whole type from a single resolved media playlist, without fetching the rest.
|
||||
*
|
||||
* Scoped to one type on purpose: propagating *across* audio/video would be wrong
|
||||
* for mixed-container sources (e.g. muxed-TS video + raw-`.aac` audio) and races
|
||||
* concurrent per-type resolution. Same-type writes are disjoint and safe.
|
||||
* Idempotent — tracks already at `mimeType` are left as-is.
|
||||
*/
|
||||
function applyContainerMimeType(presentation, type, mimeType) {
|
||||
return {
|
||||
...presentation,
|
||||
selectionSets: presentation.selectionSets.map((selectionSet) => selectionSet.type === type ? {
|
||||
...selectionSet,
|
||||
switchingSets: selectionSet.switchingSets.map((switchingSet) => ({
|
||||
...switchingSet,
|
||||
tracks: switchingSet.tracks.map((track) => track.mimeType === mimeType ? track : {
|
||||
...track,
|
||||
mimeType
|
||||
})
|
||||
}))
|
||||
} : selectionSet)
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Updates a track within a presentation (immutably). Generic — works for
|
||||
* video, audio, or text tracks.
|
||||
*/
|
||||
function updateTrackInPresentation(presentation, resolvedTrack) {
|
||||
const trackId = resolvedTrack.id;
|
||||
return {
|
||||
...presentation,
|
||||
selectionSets: presentation.selectionSets.map((selectionSet) => ({
|
||||
...selectionSet,
|
||||
switchingSets: selectionSet.switchingSets.map((switchingSet) => ({
|
||||
...switchingSet,
|
||||
tracks: switchingSet.tracks.map((track) => track.id === trackId ? resolvedTrack : track)
|
||||
}))
|
||||
}))
|
||||
};
|
||||
}
|
||||
//#endregion
|
||||
export { applyContainerMimeType, findResolvedAudioTrack, findResolvedTextTrack, findResolvedVideoTrack, findTrack, findTrackById, getTracksByType, hasCodecs, updateTrackInPresentation };
|
||||
|
||||
//# sourceMappingURL=tracks.js.map
|
||||
Vendored
+1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user