node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

160
server/node_modules/media-tracks/README.md generated vendored Normal file
View File

@@ -0,0 +1,160 @@
# Media Tracks
[![NPM Version](https://img.shields.io/npm/v/media-tracks?style=flat-square&color=informational)](https://www.npmjs.com/package/media-tracks)
[![NPM Downloads](https://img.shields.io/npm/dm/media-tracks?style=flat-square&color=informational&label=npm)](https://www.npmjs.com/package/media-tracks)
[![jsDelivr hits (npm)](https://img.shields.io/jsdelivr/npm/hm/media-tracks?style=flat-square&color=%23FF5627)](https://www.jsdelivr.com/package/npm/media-tracks)
[![npm bundle size](https://img.shields.io/bundlephobia/minzip/media-tracks?style=flat-square&color=success&label=gzip)](https://bundlephobia.com/result?p=media-tracks)
[![Codecov](https://img.shields.io/codecov/c/github/muxinc/media-tracks?style=flat-square)](https://app.codecov.io/gh/muxinc/media-tracks)
Polyfills the media elements (`<audio>` or `<video>`) adding audio and video tracks (as [specced](https://html.spec.whatwg.org/multipage/media.html#media-resources-with-multiple-media-tracks)) and with renditions as proposed in [media-ui-extensions](https://github.com/video-dev/media-ui-extensions).
- Allows media engines like [hls.js](https://github.com/video-dev/hls.js)
or [shaka](https://github.com/shaka-project/shaka-player) to add media tracks w/
renditions from the information they retrieve from the manifest to a standardized
API.
- Allows media UI implementations like [media-chrome](https://github.com/muxinc/media-chrome) to consume this uniform API and render media track selection menus
and rendition (quality) selection menus.
## Caveats
- iOS does not support manual rendition switching as it is using a native
HLS implementation. This library can't change anything about that.
## Interfaces
```ts
declare global {
interface HTMLMediaElement {
videoTracks: VideoTrackList;
audioTracks: AudioTrackList;
addVideoTrack(kind: string, label?: string, language?: string): VideoTrack;
addAudioTrack(kind: string, label?: string, language?: string): AudioTrack;
removeVideoTrack(track: VideoTrack): void;
removeAudioTrack(track: AudioTrack): void;
videoRenditions: VideoRenditionList;
audioRenditions: AudioRenditionList;
}
}
declare class VideoTrackList extends EventTarget {
[index: number]: VideoTrack;
[Symbol.iterator](): IterableIterator<VideoTrack>;
get length(): number;
getTrackById(id: string): VideoTrack | null;
get selectedIndex(): number;
get onaddtrack(): ((event?: { track: VideoTrack }) => void) | undefined;
set onaddtrack(callback: ((event?: { track: VideoTrack }) => void) | undefined);
get onremovetrack(): ((event?: { track: VideoTrack }) => void) | undefined;
set onremovetrack(callback: ((event?: { track: VideoTrack }) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}
declare const VideoTrackKind: {
alternative: string;
captions: string;
main: string;
sign: string;
subtitles: string;
commentary: string;
};
declare class VideoTrack {
id?: string;
kind?: string;
label: string;
language: string;
sourceBuffer?: SourceBuffer;
addRendition(src: string, width?: number, height?: number, codec?: string, bitrate?: number, frameRate?: number): VideoRendition;
removeRendition(rendition: AudioRendition): void;
get selected(): boolean;
set selected(val: boolean);
}
declare class VideoRenditionList extends EventTarget {
[index: number]: VideoRendition;
[Symbol.iterator](): IterableIterator<VideoRendition>;
get length(): number;
getRenditionById(id: string): VideoRendition | null;
get selectedIndex(): number;
set selectedIndex(index: number);
get onaddrendition(): ((event?: { rendition: VideoRendition }) => void) | undefined;
set onaddrendition(callback: ((event?: { rendition: VideoRendition }) => void) | undefined);
get onremoverendition(): ((event?: { rendition: VideoRendition }) => void) | undefined;
set onremoverendition(callback: ((event?: { rendition: VideoRendition }) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}
declare class VideoRendition {
src?: string;
id?: string;
width?: number;
height?: number;
bitrate?: number;
frameRate?: number;
codec?: string;
get selected(): boolean;
set selected(val: boolean);
}
declare class AudioTrackList extends EventTarget {
[index: number]: AudioTrack;
[Symbol.iterator](): IterableIterator<AudioTrack>;
get length(): number;
getTrackById(id: string): AudioTrack | null;
get onaddtrack(): ((event?: { track: AudioTrack }) => void) | undefined;
set onaddtrack(callback: ((event?: { track: AudioTrack }) => void) | undefined);
get onremovetrack(): ((event?: { track: AudioTrack }) => void) | undefined;
set onremovetrack(callback: ((event?: { track: AudioTrack }) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}
declare const AudioTrackKind: {
alternative: string;
descriptions: string;
main: string;
'main-desc': string;
translation: string;
commentary: string;
};
declare class AudioTrack {
id?: string;
kind?: string;
label: string;
language: string;
sourceBuffer?: SourceBuffer;
addRendition(src: string, codec?: string, bitrate?: number): AudioRendition;
removeRendition(rendition: AudioRendition): void;
get enabled(): boolean;
set enabled(val: boolean);
}
declare class AudioRenditionList extends EventTarget {
[index: number]: AudioRendition;
[Symbol.iterator](): IterableIterator<AudioRendition>;
get length(): number;
getRenditionById(id: string): AudioRendition | null;
get selectedIndex(): number;
set selectedIndex(index: number);
get onaddrendition(): ((event?: { rendition: VideoRendition }) => void) | undefined;
set onaddrendition(callback: ((event?: { rendition: VideoRendition }) => void) | undefined);
get onremoverendition(): ((event?: { rendition: VideoRendition }) => void) | undefined;
set onremoverendition(callback: ((event?: { rendition: VideoRendition }) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}
declare class AudioRendition {
src?: string;
id?: string;
bitrate?: number;
codec?: string;
get selected(): boolean;
set selected(val: boolean);
}
```

View File

@@ -0,0 +1,28 @@
import type { AudioTrack } from './audio-track.js';
import type { AudioRendition } from './audio-rendition.js';
export declare function addRendition(track: AudioTrack, rendition: AudioRendition): void;
export declare function removeRendition(rendition: AudioRendition): void;
export declare function selectedChanged(rendition: AudioRendition): void;
export declare class AudioRenditionList extends EventTarget {
#private;
[index: number]: AudioRendition;
[Symbol.iterator](): IterableIterator<AudioRendition>;
get length(): number;
getRenditionById(id: string): AudioRendition | null;
get selectedIndex(): number;
set selectedIndex(index: number);
get onaddrendition(): ((event?: {
rendition: AudioRendition;
}) => void) | undefined;
set onaddrendition(callback: ((event?: {
rendition: AudioRendition;
}) => void) | undefined);
get onremoverendition(): ((event?: {
rendition: AudioRendition;
}) => void) | undefined;
set onremoverendition(callback: ((event?: {
rendition: AudioRendition;
}) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}

View File

@@ -0,0 +1,114 @@
import { RenditionEvent } from "./rendition-event.js";
import { getPrivate } from "./utils.js";
function addRendition(track, rendition) {
const renditionList = getPrivate(track).media.audioRenditions;
getPrivate(rendition).media = getPrivate(track).media;
getPrivate(rendition).track = track;
const renditionSet = getPrivate(track).renditionSet;
renditionSet.add(rendition);
const index = renditionSet.size - 1;
if (!(index in AudioRenditionList.prototype)) {
Object.defineProperty(AudioRenditionList.prototype, index, {
get() {
return getCurrentRenditions(this)[index];
}
});
}
queueMicrotask(() => {
if (!track.enabled) return;
renditionList.dispatchEvent(new RenditionEvent("addrendition", { rendition }));
});
}
function removeRendition(rendition) {
const renditionList = getPrivate(rendition).media.audioRenditions;
const track = getPrivate(rendition).track;
const renditionSet = getPrivate(track).renditionSet;
renditionSet.delete(rendition);
queueMicrotask(() => {
const track2 = getPrivate(rendition).track;
if (!track2.enabled) return;
renditionList.dispatchEvent(new RenditionEvent("removerendition", { rendition }));
});
}
function selectedChanged(rendition) {
const renditionList = getPrivate(rendition).media.audioRenditions;
if (!renditionList || getPrivate(renditionList).changeRequested) return;
getPrivate(renditionList).changeRequested = true;
queueMicrotask(() => {
delete getPrivate(renditionList).changeRequested;
const track = getPrivate(rendition).track;
if (!track.enabled) return;
renditionList.dispatchEvent(new Event("change"));
});
}
function getCurrentRenditions(renditionList) {
const media = getPrivate(renditionList).media;
return [...media.audioTracks].filter((track) => track.enabled).flatMap((track) => [...getPrivate(track).renditionSet]);
}
class AudioRenditionList extends EventTarget {
#addRenditionCallback;
#removeRenditionCallback;
#changeCallback;
[Symbol.iterator]() {
return getCurrentRenditions(this).values();
}
get length() {
return getCurrentRenditions(this).length;
}
getRenditionById(id) {
return getCurrentRenditions(this).find((rendition) => `${rendition.id}` === `${id}`) ?? null;
}
get selectedIndex() {
return getCurrentRenditions(this).findIndex((rendition) => rendition.selected);
}
set selectedIndex(index) {
for (const [i, rendition] of getCurrentRenditions(this).entries()) {
rendition.selected = i === index;
}
}
get onaddrendition() {
return this.#addRenditionCallback;
}
set onaddrendition(callback) {
if (this.#addRenditionCallback) {
this.removeEventListener("addrendition", this.#addRenditionCallback);
this.#addRenditionCallback = void 0;
}
if (typeof callback == "function") {
this.#addRenditionCallback = callback;
this.addEventListener("addrendition", callback);
}
}
get onremoverendition() {
return this.#removeRenditionCallback;
}
set onremoverendition(callback) {
if (this.#removeRenditionCallback) {
this.removeEventListener("removerendition", this.#removeRenditionCallback);
this.#removeRenditionCallback = void 0;
}
if (typeof callback == "function") {
this.#removeRenditionCallback = callback;
this.addEventListener("removerendition", callback);
}
}
get onchange() {
return this.#changeCallback;
}
set onchange(callback) {
if (this.#changeCallback) {
this.removeEventListener("change", this.#changeCallback);
this.#changeCallback = void 0;
}
if (typeof callback == "function") {
this.#changeCallback = callback;
this.addEventListener("change", callback);
}
}
}
export {
AudioRenditionList,
addRendition,
removeRendition,
selectedChanged
};

View File

@@ -0,0 +1,13 @@
/**
* - The consumer should use the `selected` setter to select 1 or multiple
* renditions that the engine is allowed to play.
*/
export declare class AudioRendition {
#private;
src?: string;
id?: string;
bitrate?: number;
codec?: string;
get selected(): boolean;
set selected(val: boolean);
}

View File

@@ -0,0 +1,19 @@
import { selectedChanged } from "./audio-rendition-list.js";
class AudioRendition {
src;
id;
bitrate;
codec;
#selected = false;
get selected() {
return this.#selected;
}
set selected(val) {
if (this.#selected === val) return;
this.#selected = val;
selectedChanged(this);
}
}
export {
AudioRendition
};

View File

@@ -0,0 +1,26 @@
import type { AudioTrack } from './audio-track.js';
export declare function addAudioTrack(media: HTMLMediaElement, track: AudioTrack): void;
export declare function removeAudioTrack(track: AudioTrack): void;
export declare function enabledChanged(track: AudioTrack): void;
export declare class AudioTrackList extends EventTarget {
#private;
[index: number]: AudioTrack;
constructor();
[Symbol.iterator](): any;
get length(): any;
getTrackById(id: string): AudioTrack | null;
get onaddtrack(): ((event?: {
track: AudioTrack;
}) => void) | undefined;
set onaddtrack(callback: ((event?: {
track: AudioTrack;
}) => void) | undefined);
get onremovetrack(): ((event?: {
track: AudioTrack;
}) => void) | undefined;
set onremovetrack(callback: ((event?: {
track: AudioTrack;
}) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}

View File

@@ -0,0 +1,106 @@
import { TrackEvent } from "./track-event.js";
import { getPrivate } from "./utils.js";
function addAudioTrack(media, track) {
const trackList = media.audioTracks;
getPrivate(track).media = media;
if (!getPrivate(track).renditionSet) {
getPrivate(track).renditionSet = /* @__PURE__ */ new Set();
}
const trackSet = getPrivate(trackList).trackSet;
trackSet.add(track);
const index = trackSet.size - 1;
if (!(index in AudioTrackList.prototype)) {
Object.defineProperty(AudioTrackList.prototype, index, {
get() {
return [...getPrivate(this).trackSet][index];
}
});
}
queueMicrotask(() => {
trackList.dispatchEvent(new TrackEvent("addtrack", { track }));
});
}
function removeAudioTrack(track) {
const trackList = getPrivate(track).media?.audioTracks;
if (!trackList) return;
const trackSet = getPrivate(trackList).trackSet;
trackSet.delete(track);
queueMicrotask(() => {
trackList.dispatchEvent(new TrackEvent("removetrack", { track }));
});
}
function enabledChanged(track) {
const trackList = getPrivate(track).media.audioTracks;
if (!trackList || getPrivate(trackList).changeRequested) return;
getPrivate(trackList).changeRequested = true;
queueMicrotask(() => {
delete getPrivate(trackList).changeRequested;
trackList.dispatchEvent(new Event("change"));
});
}
class AudioTrackList extends EventTarget {
#addTrackCallback;
#removeTrackCallback;
#changeCallback;
constructor() {
super();
getPrivate(this).trackSet = /* @__PURE__ */ new Set();
}
get #tracks() {
return getPrivate(this).trackSet;
}
[Symbol.iterator]() {
return this.#tracks.values();
}
get length() {
return this.#tracks.size;
}
getTrackById(id) {
return [...this.#tracks].find((track) => track.id === id) ?? null;
}
get onaddtrack() {
return this.#addTrackCallback;
}
set onaddtrack(callback) {
if (this.#addTrackCallback) {
this.removeEventListener("addtrack", this.#addTrackCallback);
this.#addTrackCallback = void 0;
}
if (typeof callback == "function") {
this.#addTrackCallback = callback;
this.addEventListener("addtrack", callback);
}
}
get onremovetrack() {
return this.#removeTrackCallback;
}
set onremovetrack(callback) {
if (this.#removeTrackCallback) {
this.removeEventListener("removetrack", this.#removeTrackCallback);
this.#removeTrackCallback = void 0;
}
if (typeof callback == "function") {
this.#removeTrackCallback = callback;
this.addEventListener("removetrack", callback);
}
}
get onchange() {
return this.#changeCallback;
}
set onchange(callback) {
if (this.#changeCallback) {
this.removeEventListener("change", this.#changeCallback);
this.#changeCallback = void 0;
}
if (typeof callback == "function") {
this.#changeCallback = callback;
this.addEventListener("change", callback);
}
}
}
export {
AudioTrackList,
addAudioTrack,
enabledChanged,
removeAudioTrack
};

21
server/node_modules/media-tracks/dist/audio-track.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import { AudioRendition } from './audio-rendition.js';
export declare const AudioTrackKind: {
alternative: string;
descriptions: string;
main: string;
'main-desc': string;
translation: string;
commentary: string;
};
export declare class AudioTrack {
#private;
id?: string;
kind?: string;
label: string;
language: string;
sourceBuffer?: SourceBuffer;
addRendition(src: string, codec?: string, bitrate?: number): AudioRendition;
removeRendition(rendition: AudioRendition): void;
get enabled(): boolean;
set enabled(val: boolean);
}

42
server/node_modules/media-tracks/dist/audio-track.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
import { AudioRendition } from "./audio-rendition.js";
import { enabledChanged } from "./audio-track-list.js";
import { addRendition, removeRendition } from "./audio-rendition-list.js";
const AudioTrackKind = {
alternative: "alternative",
descriptions: "descriptions",
main: "main",
"main-desc": "main-desc",
translation: "translation",
commentary: "commentary"
};
class AudioTrack {
id;
kind;
label = "";
language = "";
sourceBuffer;
#enabled = false;
addRendition(src, codec, bitrate) {
const rendition = new AudioRendition();
rendition.src = src;
rendition.codec = codec;
rendition.bitrate = bitrate;
addRendition(this, rendition);
return rendition;
}
removeRendition(rendition) {
removeRendition(rendition);
}
get enabled() {
return this.#enabled;
}
set enabled(val) {
if (this.#enabled === val) return;
this.#enabled = val;
enabledChanged(this);
}
}
export {
AudioTrack,
AudioTrackKind
};

18
server/node_modules/media-tracks/dist/global.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
import type { VideoTrack } from './video-track.js';
import type { VideoTrackList } from './video-track-list.js';
import type { AudioTrack } from './audio-track.js';
import type { AudioTrackList } from './audio-track-list.js';
import type { VideoRenditionList } from './video-rendition-list.js';
import type { AudioRenditionList } from './audio-rendition-list.js';
declare global {
interface HTMLMediaElement {
videoTracks: VideoTrackList;
audioTracks: AudioTrackList;
addVideoTrack(kind: string, label?: string, language?: string): VideoTrack;
addAudioTrack(kind: string, label?: string, language?: string): AudioTrack;
removeVideoTrack(track: VideoTrack): void;
removeAudioTrack(track: AudioTrack): void;
videoRenditions: VideoRenditionList;
audioRenditions: AudioRenditionList;
}
}

0
server/node_modules/media-tracks/dist/global.js generated vendored Normal file
View File

11
server/node_modules/media-tracks/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,11 @@
export * from './mixin.js';
export { VideoTrack } from './video-track.js';
export { VideoTrackList } from './video-track-list.js';
export { VideoRendition } from './video-rendition.js';
export { VideoRenditionList } from './video-rendition-list.js';
export { AudioTrack } from './audio-track.js';
export { AudioTrackList } from './audio-track-list.js';
export { AudioRendition } from './audio-rendition.js';
export { AudioRenditionList } from './audio-rendition-list.js';
export { TrackEvent } from './track-event.js';
export { RenditionEvent } from './rendition-event.js';

23
server/node_modules/media-tracks/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
export * from "./mixin.js";
import { VideoTrack } from "./video-track.js";
import { VideoTrackList } from "./video-track-list.js";
import { VideoRendition } from "./video-rendition.js";
import { VideoRenditionList } from "./video-rendition-list.js";
import { AudioTrack } from "./audio-track.js";
import { AudioTrackList } from "./audio-track-list.js";
import { AudioRendition } from "./audio-rendition.js";
import { AudioRenditionList } from "./audio-rendition-list.js";
import { TrackEvent } from "./track-event.js";
import { RenditionEvent } from "./rendition-event.js";
export {
AudioRendition,
AudioRenditionList,
AudioTrack,
AudioTrackList,
RenditionEvent,
TrackEvent,
VideoRendition,
VideoRenditionList,
VideoTrack,
VideoTrackList
};

23
server/node_modules/media-tracks/dist/mixin.d.ts generated vendored Normal file
View File

@@ -0,0 +1,23 @@
import { VideoTrack } from './video-track.js';
import { VideoTrackList } from './video-track-list.js';
import { AudioTrack } from './audio-track.js';
import { AudioTrackList } from './audio-track-list.js';
import { VideoRenditionList } from './video-rendition-list.js';
import { AudioRenditionList } from './audio-rendition-list.js';
declare interface MediaTracks {
videoTracks: VideoTrackList;
audioTracks: AudioTrackList;
addVideoTrack(kind: string, label?: string, language?: string): VideoTrack;
addAudioTrack(kind: string, label?: string, language?: string): AudioTrack;
removeVideoTrack(track: VideoTrack): void;
removeAudioTrack(track: AudioTrack): void;
videoRenditions: VideoRenditionList;
audioRenditions: AudioRenditionList;
}
declare type Constructor<T> = {
new (...args: any[]): T;
prototype: T;
};
export type WithMediaTracks<T> = T & Constructor<MediaTracks>;
export declare function MediaTracksMixin<T>(MediaElementClass: T): WithMediaTracks<T>;
export {};

153
server/node_modules/media-tracks/dist/mixin.js generated vendored Normal file
View File

@@ -0,0 +1,153 @@
import { VideoTrack } from "./video-track.js";
import { VideoTrackList, addVideoTrack, removeVideoTrack } from "./video-track-list.js";
import { AudioTrack } from "./audio-track.js";
import { AudioTrackList, addAudioTrack, removeAudioTrack } from "./audio-track-list.js";
import { VideoRenditionList } from "./video-rendition-list.js";
import { AudioRenditionList } from "./audio-rendition-list.js";
import { getPrivate } from "./utils.js";
const nativeVideoTracksFn = getBaseMediaTracksFn(globalThis.HTMLMediaElement, "video");
const nativeAudioTracksFn = getBaseMediaTracksFn(globalThis.HTMLMediaElement, "audio");
function MediaTracksMixin(MediaElementClass) {
if (!MediaElementClass?.prototype) return MediaElementClass;
const videoTracksFn = getBaseMediaTracksFn(MediaElementClass, "video");
if (!videoTracksFn || `${videoTracksFn}`.includes("[native code]")) {
Object.defineProperty(MediaElementClass.prototype, "videoTracks", {
get() {
return getVideoTracks(this);
}
});
}
const audioTracksFn = getBaseMediaTracksFn(MediaElementClass, "audio");
if (!audioTracksFn || `${audioTracksFn}`.includes("[native code]")) {
Object.defineProperty(MediaElementClass.prototype, "audioTracks", {
get() {
return getAudioTracks(this);
}
});
}
if (!("addVideoTrack" in MediaElementClass.prototype)) {
MediaElementClass.prototype.addVideoTrack = function(kind, label = "", language = "") {
const track = new VideoTrack();
track.kind = kind;
track.label = label;
track.language = language;
addVideoTrack(this, track);
return track;
};
}
if (!("removeVideoTrack" in MediaElementClass.prototype)) {
MediaElementClass.prototype.removeVideoTrack = removeVideoTrack;
}
if (!("addAudioTrack" in MediaElementClass.prototype)) {
MediaElementClass.prototype.addAudioTrack = function(kind, label = "", language = "") {
const track = new AudioTrack();
track.kind = kind;
track.label = label;
track.language = language;
addAudioTrack(this, track);
return track;
};
}
if (!("removeAudioTrack" in MediaElementClass.prototype)) {
MediaElementClass.prototype.removeAudioTrack = removeAudioTrack;
}
if (!("videoRenditions" in MediaElementClass.prototype)) {
Object.defineProperty(MediaElementClass.prototype, "videoRenditions", {
get() {
return initVideoRenditions(this);
}
});
}
const initVideoRenditions = (media) => {
let renditions = getPrivate(media).videoRenditions;
if (!renditions) {
renditions = new VideoRenditionList();
getPrivate(renditions).media = media;
getPrivate(media).videoRenditions = renditions;
}
return renditions;
};
if (!("audioRenditions" in MediaElementClass.prototype)) {
Object.defineProperty(MediaElementClass.prototype, "audioRenditions", {
get() {
return initAudioRenditions(this);
}
});
}
const initAudioRenditions = (media) => {
let renditions = getPrivate(media).audioRenditions;
if (!renditions) {
renditions = new AudioRenditionList();
getPrivate(renditions).media = media;
getPrivate(media).audioRenditions = renditions;
}
return renditions;
};
return MediaElementClass;
}
function getBaseMediaTracksFn(MediaElementClass, type) {
if (MediaElementClass?.prototype) {
return Object.getOwnPropertyDescriptor(MediaElementClass.prototype, `${type}Tracks`)?.get;
}
}
function getVideoTracks(media) {
let tracks = getPrivate(media).videoTracks;
if (!tracks) {
tracks = new VideoTrackList();
getPrivate(media).videoTracks = tracks;
if (nativeVideoTracksFn) {
const nativeTracks = nativeVideoTracksFn.call(media.nativeEl ?? media);
for (const nativeTrack of nativeTracks) {
addVideoTrack(media, nativeTrack);
}
nativeTracks.addEventListener("change", () => {
tracks.dispatchEvent(new Event("change"));
});
nativeTracks.addEventListener("addtrack", (event) => {
if ([...tracks].some((t) => t instanceof VideoTrack)) {
for (const nativeTrack of nativeTracks) {
removeVideoTrack(nativeTrack);
}
return;
}
addVideoTrack(media, event.track);
});
nativeTracks.addEventListener("removetrack", (event) => {
removeVideoTrack(event.track);
});
}
}
return tracks;
}
function getAudioTracks(media) {
let tracks = getPrivate(media).audioTracks;
if (!tracks) {
tracks = new AudioTrackList();
getPrivate(media).audioTracks = tracks;
if (nativeAudioTracksFn) {
const nativeTracks = nativeAudioTracksFn.call(media.nativeEl ?? media);
for (const nativeTrack of nativeTracks) {
addAudioTrack(media, nativeTrack);
}
nativeTracks.addEventListener("change", () => {
tracks.dispatchEvent(new Event("change"));
});
nativeTracks.addEventListener("addtrack", (event) => {
if ([...tracks].some((t) => t instanceof AudioTrack)) {
for (const nativeTrack of nativeTracks) {
removeAudioTrack(nativeTrack);
}
return;
}
addAudioTrack(media, event.track);
});
nativeTracks.addEventListener("removetrack", (event) => {
removeAudioTrack(event.track);
});
}
}
return tracks;
}
export {
MediaTracksMixin
};

1
server/node_modules/media-tracks/dist/polyfill.d.ts generated vendored Normal file
View File

@@ -0,0 +1 @@
export {};

2
server/node_modules/media-tracks/dist/polyfill.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
import { MediaTracksMixin } from "./mixin.js";
MediaTracksMixin(globalThis.HTMLMediaElement);

View File

@@ -0,0 +1,6 @@
import type { AudioRendition } from './audio-rendition.js';
import type { VideoRendition } from './video-rendition.js';
export declare class RenditionEvent extends Event {
rendition: VideoRendition | AudioRendition;
constructor(type: string, init: Record<string, VideoRendition | AudioRendition>);
}

View File

@@ -0,0 +1,10 @@
class RenditionEvent extends Event {
rendition;
constructor(type, init) {
super(type);
this.rendition = init.rendition;
}
}
export {
RenditionEvent
};

View File

@@ -0,0 +1,6 @@
import type { AudioTrack } from './audio-track.js';
import type { VideoTrack } from './video-track.js';
export declare class TrackEvent extends Event {
track: VideoTrack | AudioTrack;
constructor(type: string, init: Record<string, VideoTrack | AudioTrack>);
}

10
server/node_modules/media-tracks/dist/track-event.js generated vendored Normal file
View File

@@ -0,0 +1,10 @@
class TrackEvent extends Event {
track;
constructor(type, init) {
super(type);
this.track = init.track;
}
}
export {
TrackEvent
};

2
server/node_modules/media-tracks/dist/utils.d.ts generated vendored Normal file
View File

@@ -0,0 +1,2 @@
export declare function getPrivate(instance: object): any;
export declare function setPrivate(instance: object, props: Record<string, any>): any;

13
server/node_modules/media-tracks/dist/utils.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
const privateProps = /* @__PURE__ */ new WeakMap();
function getPrivate(instance) {
return privateProps.get(instance) ?? setPrivate(instance, {});
}
function setPrivate(instance, props) {
let saved = privateProps.get(instance);
if (!saved) privateProps.set(instance, saved = {});
return Object.assign(saved, props);
}
export {
getPrivate,
setPrivate
};

View File

@@ -0,0 +1,28 @@
import type { VideoTrack } from './video-track.js';
import type { VideoRendition } from './video-rendition.js';
export declare function addRendition(track: VideoTrack, rendition: VideoRendition): void;
export declare function removeRendition(rendition: VideoRendition): void;
export declare function selectedChanged(rendition: VideoRendition): void;
export declare class VideoRenditionList extends EventTarget {
#private;
[index: number]: VideoRendition;
[Symbol.iterator](): IterableIterator<VideoRendition>;
get length(): number;
getRenditionById(id: string): VideoRendition | null;
get selectedIndex(): number;
set selectedIndex(index: number);
get onaddrendition(): ((event?: {
rendition: VideoRendition;
}) => void) | undefined;
set onaddrendition(callback: ((event?: {
rendition: VideoRendition;
}) => void) | undefined);
get onremoverendition(): ((event?: {
rendition: VideoRendition;
}) => void) | undefined;
set onremoverendition(callback: ((event?: {
rendition: VideoRendition;
}) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}

View File

@@ -0,0 +1,114 @@
import { RenditionEvent } from "./rendition-event.js";
import { getPrivate } from "./utils.js";
function addRendition(track, rendition) {
const renditionList = getPrivate(track).media.videoRenditions;
getPrivate(rendition).media = getPrivate(track).media;
getPrivate(rendition).track = track;
const renditionSet = getPrivate(track).renditionSet;
renditionSet.add(rendition);
const index = renditionSet.size - 1;
if (!(index in VideoRenditionList.prototype)) {
Object.defineProperty(VideoRenditionList.prototype, index, {
get() {
return getCurrentRenditions(this)[index];
}
});
}
queueMicrotask(() => {
if (!track.selected) return;
renditionList.dispatchEvent(new RenditionEvent("addrendition", { rendition }));
});
}
function removeRendition(rendition) {
const renditionList = getPrivate(rendition).media.videoRenditions;
const track = getPrivate(rendition).track;
const renditionSet = getPrivate(track).renditionSet;
renditionSet.delete(rendition);
queueMicrotask(() => {
const track2 = getPrivate(rendition).track;
if (!track2.selected) return;
renditionList.dispatchEvent(new RenditionEvent("removerendition", { rendition }));
});
}
function selectedChanged(rendition) {
const renditionList = getPrivate(rendition).media.videoRenditions;
if (!renditionList || getPrivate(renditionList).changeRequested) return;
getPrivate(renditionList).changeRequested = true;
queueMicrotask(() => {
delete getPrivate(renditionList).changeRequested;
const track = getPrivate(rendition).track;
if (!track.selected) return;
renditionList.dispatchEvent(new Event("change"));
});
}
function getCurrentRenditions(renditionList) {
const media = getPrivate(renditionList).media;
return [...media.videoTracks].filter((track) => track.selected).flatMap((track) => [...getPrivate(track).renditionSet]);
}
class VideoRenditionList extends EventTarget {
#addRenditionCallback;
#removeRenditionCallback;
#changeCallback;
[Symbol.iterator]() {
return getCurrentRenditions(this).values();
}
get length() {
return getCurrentRenditions(this).length;
}
getRenditionById(id) {
return getCurrentRenditions(this).find((rendition) => `${rendition.id}` === `${id}`) ?? null;
}
get selectedIndex() {
return getCurrentRenditions(this).findIndex((rendition) => rendition.selected);
}
set selectedIndex(index) {
for (const [i, rendition] of getCurrentRenditions(this).entries()) {
rendition.selected = i === index;
}
}
get onaddrendition() {
return this.#addRenditionCallback;
}
set onaddrendition(callback) {
if (this.#addRenditionCallback) {
this.removeEventListener("addrendition", this.#addRenditionCallback);
this.#addRenditionCallback = void 0;
}
if (typeof callback == "function") {
this.#addRenditionCallback = callback;
this.addEventListener("addrendition", callback);
}
}
get onremoverendition() {
return this.#removeRenditionCallback;
}
set onremoverendition(callback) {
if (this.#removeRenditionCallback) {
this.removeEventListener("removerendition", this.#removeRenditionCallback);
this.#removeRenditionCallback = void 0;
}
if (typeof callback == "function") {
this.#removeRenditionCallback = callback;
this.addEventListener("removerendition", callback);
}
}
get onchange() {
return this.#changeCallback;
}
set onchange(callback) {
if (this.#changeCallback) {
this.removeEventListener("change", this.#changeCallback);
this.#changeCallback = void 0;
}
if (typeof callback == "function") {
this.#changeCallback = callback;
this.addEventListener("change", callback);
}
}
}
export {
VideoRenditionList,
addRendition,
removeRendition,
selectedChanged
};

View File

@@ -0,0 +1,16 @@
/**
* - The consumer should use the `selected` setter to select 1 or multiple
* renditions that the engine is allowed to play.
*/
export declare class VideoRendition {
#private;
src?: string;
id?: string;
width?: number;
height?: number;
bitrate?: number;
frameRate?: number;
codec?: string;
get selected(): boolean;
set selected(val: boolean);
}

View File

@@ -0,0 +1,22 @@
import { selectedChanged } from "./video-rendition-list.js";
class VideoRendition {
src;
id;
width;
height;
bitrate;
frameRate;
codec;
#selected = false;
get selected() {
return this.#selected;
}
set selected(val) {
if (this.#selected === val) return;
this.#selected = val;
selectedChanged(this);
}
}
export {
VideoRendition
};

View File

@@ -0,0 +1,27 @@
import type { VideoTrack } from './video-track.js';
export declare function addVideoTrack(media: HTMLMediaElement, track: VideoTrack): void;
export declare function removeVideoTrack(track: VideoTrack): void;
export declare function selectedChanged(selected: VideoTrack): void;
export declare class VideoTrackList extends EventTarget {
#private;
[index: number]: VideoTrack;
constructor();
[Symbol.iterator](): any;
get length(): any;
getTrackById(id: string): VideoTrack | null;
get selectedIndex(): number;
get onaddtrack(): ((event?: {
track: VideoTrack;
}) => void) | undefined;
set onaddtrack(callback: ((event?: {
track: VideoTrack;
}) => void) | undefined);
get onremovetrack(): ((event?: {
track: VideoTrack;
}) => void) | undefined;
set onremovetrack(callback: ((event?: {
track: VideoTrack;
}) => void) | undefined);
get onchange(): (() => void) | undefined;
set onchange(callback: (() => void) | undefined);
}

View File

@@ -0,0 +1,117 @@
import { TrackEvent } from "./track-event.js";
import { getPrivate } from "./utils.js";
function addVideoTrack(media, track) {
const trackList = media.videoTracks;
getPrivate(track).media = media;
if (!getPrivate(track).renditionSet) {
getPrivate(track).renditionSet = /* @__PURE__ */ new Set();
}
const trackSet = getPrivate(trackList).trackSet;
trackSet.add(track);
const index = trackSet.size - 1;
if (!(index in VideoTrackList.prototype)) {
Object.defineProperty(VideoTrackList.prototype, index, {
get() {
return [...getPrivate(this).trackSet][index];
}
});
}
queueMicrotask(() => {
trackList.dispatchEvent(new TrackEvent("addtrack", { track }));
});
}
function removeVideoTrack(track) {
const trackList = getPrivate(track).media?.videoTracks;
if (!trackList) return;
const trackSet = getPrivate(trackList).trackSet;
trackSet.delete(track);
queueMicrotask(() => {
trackList.dispatchEvent(new TrackEvent("removetrack", { track }));
});
}
function selectedChanged(selected) {
const trackList = getPrivate(selected).media.videoTracks ?? [];
let hasUnselected = false;
for (const track of trackList) {
if (track === selected) continue;
track.selected = false;
hasUnselected = true;
}
if (hasUnselected) {
if (getPrivate(trackList).changeRequested) return;
getPrivate(trackList).changeRequested = true;
queueMicrotask(() => {
delete getPrivate(trackList).changeRequested;
trackList.dispatchEvent(new Event("change"));
});
}
}
class VideoTrackList extends EventTarget {
#addTrackCallback;
#removeTrackCallback;
#changeCallback;
constructor() {
super();
getPrivate(this).trackSet = /* @__PURE__ */ new Set();
}
get #tracks() {
return getPrivate(this).trackSet;
}
[Symbol.iterator]() {
return this.#tracks.values();
}
get length() {
return this.#tracks.size;
}
getTrackById(id) {
return [...this.#tracks].find((track) => track.id === id) ?? null;
}
get selectedIndex() {
return [...this.#tracks].findIndex((track) => track.selected);
}
get onaddtrack() {
return this.#addTrackCallback;
}
set onaddtrack(callback) {
if (this.#addTrackCallback) {
this.removeEventListener("addtrack", this.#addTrackCallback);
this.#addTrackCallback = void 0;
}
if (typeof callback == "function") {
this.#addTrackCallback = callback;
this.addEventListener("addtrack", callback);
}
}
get onremovetrack() {
return this.#removeTrackCallback;
}
set onremovetrack(callback) {
if (this.#removeTrackCallback) {
this.removeEventListener("removetrack", this.#removeTrackCallback);
this.#removeTrackCallback = void 0;
}
if (typeof callback == "function") {
this.#removeTrackCallback = callback;
this.addEventListener("removetrack", callback);
}
}
get onchange() {
return this.#changeCallback;
}
set onchange(callback) {
if (this.#changeCallback) {
this.removeEventListener("change", this.#changeCallback);
this.#changeCallback = void 0;
}
if (typeof callback == "function") {
this.#changeCallback = callback;
this.addEventListener("change", callback);
}
}
}
export {
VideoTrackList,
addVideoTrack,
removeVideoTrack,
selectedChanged
};

21
server/node_modules/media-tracks/dist/video-track.d.ts generated vendored Normal file
View File

@@ -0,0 +1,21 @@
import { VideoRendition } from './video-rendition.js';
export declare const VideoTrackKind: {
alternative: string;
captions: string;
main: string;
sign: string;
subtitles: string;
commentary: string;
};
export declare class VideoTrack {
#private;
id?: string;
kind?: string;
label: string;
language: string;
sourceBuffer?: SourceBuffer;
addRendition(src: string, width?: number, height?: number, codec?: string, bitrate?: number, frameRate?: number): VideoRendition;
removeRendition(rendition: VideoRendition): void;
get selected(): boolean;
set selected(val: boolean);
}

46
server/node_modules/media-tracks/dist/video-track.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
import { selectedChanged } from "./video-track-list.js";
import { VideoRendition } from "./video-rendition.js";
import { addRendition, removeRendition } from "./video-rendition-list.js";
const VideoTrackKind = {
alternative: "alternative",
captions: "captions",
main: "main",
sign: "sign",
subtitles: "subtitles",
commentary: "commentary"
};
class VideoTrack {
id;
kind;
label = "";
language = "";
sourceBuffer;
#selected = false;
addRendition(src, width, height, codec, bitrate, frameRate) {
const rendition = new VideoRendition();
rendition.src = src;
rendition.width = width;
rendition.height = height;
rendition.frameRate = frameRate;
rendition.bitrate = bitrate;
rendition.codec = codec;
addRendition(this, rendition);
return rendition;
}
removeRendition(rendition) {
removeRendition(rendition);
}
get selected() {
return this.#selected;
}
set selected(val) {
if (this.#selected === val) return;
this.#selected = val;
if (val !== true) return;
selectedChanged(this);
}
}
export {
VideoTrack,
VideoTrackKind
};

70
server/node_modules/media-tracks/package.json generated vendored Normal file
View File

@@ -0,0 +1,70 @@
{
"name": "media-tracks",
"version": "0.3.3",
"description": "Polyfill audio and video tracks with renditions.",
"author": "@muxinc",
"license": "MIT",
"homepage": "https://github.com/muxinc/media-tracks#readme",
"bugs": {
"url": "https://github.com/muxinc/media-tracks/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/muxinc/media-elements.git",
"directory": "packages/media-tracks"
},
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": "./dist/index.js",
"./polyfill": "./dist/polyfill.js"
},
"files": [
"dist"
],
"scripts": {
"lint": "eslint src/*.ts",
"pretest": "npm run build -- --sourcemap=inline",
"test": "npm run test:types && wet test --coverage",
"test:types": "tsc test/test.js --module nodenext --moduleResolution nodenext --target esnext --noEmit --allowJs",
"dev": "tsc -w & esbuild src/*.ts --format=esm --outdir=dist --watch=forever",
"build": "rm -rf dist && esbuild src/*.ts --format=esm --outdir=dist",
"postbuild": "tsc"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
"esbuild": "^0.21.4",
"typescript": "5.4.5",
"wet-run": "^1.2.2"
},
"eslintConfig": {
"root": true,
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"globals": {
"globalThis": "writable"
},
"env": {
"browser": true,
"es6": true,
"node": true,
"mocha": true
},
"parserOptions": {
"ecmaVersion": 2022,
"sourceType": "module"
},
"rules": {
"@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-explicit-any": 0
}
}
}