Files
v10/packages/core/playback-engine/src/HlsJSPlaybackEngine.ts
T

81 lines
2.2 KiB
TypeScript

import Hls from 'hls.js';
/** @TODO Move interface/type defs (CJP) */
/** @TODO Narrow and/or parameterize EventTarget via generics/inference (CJP) */
export interface IBasePlaybackEngine extends EventTarget {
src: HTMLMediaElement['src'] | undefined;
// NOTE: Unlike other APIs, this *must* be an HTMLMediaElement based on internal and/or external API assumptions (CJP)
mediaElement: HTMLMediaElement | undefined;
/** @TODO Widen/extend and/or parameterize EventTarget via generics/inference (CJP) */
element: HTMLElement | undefined;
destroy: () => void;
}
export class HlsJSPlaybackEngine extends EventTarget {
constructor() {
super();
}
protected _hlsInstance: Hls | undefined;
get src(): string | undefined {
return this._hlsInstance?.url ?? undefined;
}
set src(src: string | undefined) {
if (this.src === src) return;
if (!this._hlsInstance) {
this._createHlsInstance();
}
if (!this.src && src) {
this._hlsInstance?.loadSource(src);
}
}
// NOTE: Some playback engines may not rely on an underlying HTMLMediaElement but still have
// an HTMLElement (e.g. HTMLCanvasElement, HTMLImageElement, etc.). This API provides a more
// generic interface for cases where we want more minimal assumptions (e.g. fullscreen behaviors for most playtforms but not iOS)
get element(): HTMLElement | undefined {
return this.mediaElement;
}
set element(val) {
if (this.element === val) return;
/** @TODO programmatic type checking? (CJP) */
this.mediaElement = val as HTMLMediaElement;
}
get mediaElement(): HTMLMediaElement | undefined {
return this._hlsInstance?.media ?? undefined;
}
set mediaElement(val) {
if (this.mediaElement === val) return;
if (!this._hlsInstance) {
this._createHlsInstance();
}
if (!this.mediaElement && val) {
this._hlsInstance?.attachMedia(val);
}
}
protected _createHlsInstance(): void {
this._hlsInstance = new Hls();
}
protected _destroyHlsInstance(): void {
this._hlsInstance?.destroy();
this._hlsInstance = undefined;
}
destroy(): void {
this._destroyHlsInstance();
}
}
export const createPlaybackEngine = (): IBasePlaybackEngine => new HlsJSPlaybackEngine();