Compare commits
2 Commits
tach-typog
...
video-play
| Author | SHA1 | Date | |
|---|---|---|---|
| e4e6bc5af4 | |||
| 028ce21c4c |
@@ -105,6 +105,8 @@ export declare class VideoPlayerRuntime {
|
|||||||
private currentEngine;
|
private currentEngine;
|
||||||
private currentSource;
|
private currentSource;
|
||||||
private vhsAuthTokenRef;
|
private vhsAuthTokenRef;
|
||||||
|
private hlsAuthTokenRef;
|
||||||
|
private hlsTokenResolvePromise;
|
||||||
private vhsRequestCleanupRef;
|
private vhsRequestCleanupRef;
|
||||||
private visibilityObserverRef;
|
private visibilityObserverRef;
|
||||||
private originalPlayRef;
|
private originalPlayRef;
|
||||||
@@ -116,6 +118,8 @@ export declare class VideoPlayerRuntime {
|
|||||||
dispose(): void;
|
dispose(): void;
|
||||||
getState(): VideoPlayerRuntimeState;
|
getState(): VideoPlayerRuntimeState;
|
||||||
getPlayer(): VideoPlayerRuntimePlayer | null;
|
getPlayer(): VideoPlayerRuntimePlayer | null;
|
||||||
|
private ensureHlsAuthToken;
|
||||||
|
private refreshHlsAuthTokenInBackground;
|
||||||
private emit;
|
private emit;
|
||||||
private tryPlay;
|
private tryPlay;
|
||||||
private resolveEngine;
|
private resolveEngine;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"player-runtime.d.ts","sourceRoot":"","sources":["../../src/core/player-runtime.ts"],"names":[],"mappings":"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"}
|
{"version":3,"file":"player-runtime.d.ts","sourceRoot":"","sources":["../../src/core/player-runtime.ts"],"names":[],"mappings":"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"}
|
||||||
@@ -12,37 +12,30 @@ const detectIOS = () => {
|
|||||||
const userAgent = navigator.userAgent || "";
|
const userAgent = navigator.userAgent || "";
|
||||||
return /iPad|iPhone|iPod/.test(userAgent);
|
return /iPad|iPhone|iPod/.test(userAgent);
|
||||||
};
|
};
|
||||||
const createAuthPlaylistLoader = ({ debug, }) => {
|
const createAuthPlaylistLoader = ({ debug, getToken, refreshToken, }) => {
|
||||||
const BaseLoader = Hls.DefaultConfig.loader;
|
const BaseLoader = Hls.DefaultConfig.loader;
|
||||||
return class AuthPlaylistLoader extends BaseLoader {
|
return class AuthPlaylistLoader extends BaseLoader {
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
super({ ...config, debug: debug ?? false });
|
super({ ...config, debug: debug ?? false });
|
||||||
}
|
}
|
||||||
load(context, config, callbacks) {
|
load(context, config, callbacks) {
|
||||||
const start = async () => {
|
try {
|
||||||
try {
|
const token = getToken();
|
||||||
const token = await resolveVideoPlayerToken();
|
if (token) {
|
||||||
if (token) {
|
context.headers = {
|
||||||
context.headers = {
|
...(context.headers ?? {}),
|
||||||
...(context.headers ?? {}),
|
Authorization: `Bearer ${token}`,
|
||||||
Authorization: `Bearer ${token}`,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
}
|
||||||
if (debug) {
|
catch (error) {
|
||||||
console.warn("[VideoRuntime:HLS] Failed to append auth header to playlist request", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
super.load(context, config, callbacks);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
void start().catch(error => {
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.error("[VideoRuntime:HLS] Playlist loader start failed", error);
|
console.warn("[VideoRuntime:HLS] Failed to append auth header to playlist request", error);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
// Critical path must stay sync for hls.js loader lifecycle.
|
||||||
|
super.load(context, config, callbacks);
|
||||||
|
refreshToken();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -82,6 +75,8 @@ export class VideoPlayerRuntime {
|
|||||||
this.currentEngine = null;
|
this.currentEngine = null;
|
||||||
this.currentSource = null;
|
this.currentSource = null;
|
||||||
this.vhsAuthTokenRef = null;
|
this.vhsAuthTokenRef = null;
|
||||||
|
this.hlsAuthTokenRef = null;
|
||||||
|
this.hlsTokenResolvePromise = null;
|
||||||
this.vhsRequestCleanupRef = null;
|
this.vhsRequestCleanupRef = null;
|
||||||
this.visibilityObserverRef = null;
|
this.visibilityObserverRef = null;
|
||||||
this.originalPlayRef = null;
|
this.originalPlayRef = null;
|
||||||
@@ -147,6 +142,8 @@ export class VideoPlayerRuntime {
|
|||||||
this.vhsRequestCleanupRef?.();
|
this.vhsRequestCleanupRef?.();
|
||||||
this.vhsRequestCleanupRef = null;
|
this.vhsRequestCleanupRef = null;
|
||||||
this.vhsAuthTokenRef = null;
|
this.vhsAuthTokenRef = null;
|
||||||
|
this.hlsAuthTokenRef = null;
|
||||||
|
this.hlsTokenResolvePromise = null;
|
||||||
if (this.playerRef) {
|
if (this.playerRef) {
|
||||||
this.playerRef.dispose();
|
this.playerRef.dispose();
|
||||||
}
|
}
|
||||||
@@ -171,6 +168,29 @@ export class VideoPlayerRuntime {
|
|||||||
getPlayer() {
|
getPlayer() {
|
||||||
return this.playerRef;
|
return this.playerRef;
|
||||||
}
|
}
|
||||||
|
async ensureHlsAuthToken() {
|
||||||
|
if (this.hlsTokenResolvePromise !== null) {
|
||||||
|
await this.hlsTokenResolvePromise;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.hlsTokenResolvePromise = resolveVideoPlayerToken()
|
||||||
|
.then(token => {
|
||||||
|
this.hlsAuthTokenRef = token ?? null;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.hlsAuthTokenRef = null;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.hlsTokenResolvePromise = null;
|
||||||
|
});
|
||||||
|
await this.hlsTokenResolvePromise;
|
||||||
|
}
|
||||||
|
refreshHlsAuthTokenInBackground() {
|
||||||
|
if (this.hlsTokenResolvePromise !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
void this.ensureHlsAuthToken();
|
||||||
|
}
|
||||||
emit(event, payload) {
|
emit(event, payload) {
|
||||||
const listeners = this.eventListeners.get(event);
|
const listeners = this.eventListeners.get(event);
|
||||||
if (!listeners?.size) {
|
if (!listeners?.size) {
|
||||||
@@ -417,7 +437,11 @@ export class VideoPlayerRuntime {
|
|||||||
const preferHqSettings = options.preferHQ
|
const preferHqSettings = options.preferHQ
|
||||||
? { abrEwmaDefaultEstimate: 10690560 * 1.2 }
|
? { abrEwmaDefaultEstimate: 10690560 * 1.2 }
|
||||||
: {};
|
: {};
|
||||||
const playlistLoader = createAuthPlaylistLoader({ debug: options.debug });
|
const playlistLoader = createAuthPlaylistLoader({
|
||||||
|
debug: options.debug,
|
||||||
|
getToken: () => this.hlsAuthTokenRef,
|
||||||
|
refreshToken: () => this.refreshHlsAuthTokenInBackground(),
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
debug: options.debug,
|
debug: options.debug,
|
||||||
enableWorker: true,
|
enableWorker: true,
|
||||||
@@ -456,6 +480,8 @@ export class VideoPlayerRuntime {
|
|||||||
await this.loadVideoJsSource();
|
await this.loadVideoJsSource();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Resolve async token before starting HLS manifest load.
|
||||||
|
await this.ensureHlsAuthToken();
|
||||||
const setupHls = () => {
|
const setupHls = () => {
|
||||||
if (this.hlsLoaded) {
|
if (this.hlsLoaded) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hublib-web/video-player",
|
"name": "@hublib-web/video-player",
|
||||||
"version": "0.1.0",
|
"version": "0.1.2",
|
||||||
"description": "Cross-framework video player package for React and Angular",
|
"description": "Cross-framework video player package for React and Angular",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
"sideEffects": true,
|
"sideEffects": true,
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
"README.md"
|
"README.md",
|
||||||
|
"scripts"
|
||||||
],
|
],
|
||||||
"typesVersions": {
|
"typesVersions": {
|
||||||
"*": {
|
"*": {
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"postinstall": "node ./scripts/apply-videojs-patch.mjs",
|
||||||
"build": "yarn clean && node ./scripts/build.mjs",
|
"build": "yarn clean && node ./scripts/build.mjs",
|
||||||
"clean": "rm -rf dist storybook-static",
|
"clean": "rm -rf dist storybook-static",
|
||||||
"typecheck": "tsc -p ./tsconfig.json --noEmit",
|
"typecheck": "tsc -p ./tsconfig.json --noEmit",
|
||||||
|
|||||||
45
packages/video-player/scripts/apply-videojs-patch.mjs
Normal file
45
packages/video-player/scripts/apply-videojs-patch.mjs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { readFileSync, writeFileSync } from "node:fs";
|
||||||
|
import { dirname, join } from "node:path";
|
||||||
|
import { createRequire } from "node:module";
|
||||||
|
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
|
const originalSnippet = ` const originalAbort = request.abort;
|
||||||
|
request.abort = function () {
|
||||||
|
request.aborted = true;
|
||||||
|
return originalAbort.apply(request, arguments);
|
||||||
|
};`;
|
||||||
|
|
||||||
|
const patchedSnippet = ` // const originalAbort = request.abort;
|
||||||
|
// request.abort = function () {
|
||||||
|
// request.aborted = true;
|
||||||
|
// return originalAbort.apply(request, arguments);
|
||||||
|
// };`;
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
const packageJsonPath = require.resolve("video.js/package.json");
|
||||||
|
const videoEsPath = join(dirname(packageJsonPath), "dist", "video.es.js");
|
||||||
|
const source = readFileSync(videoEsPath, "utf8");
|
||||||
|
|
||||||
|
if (source.includes(patchedSnippet)) {
|
||||||
|
console.log("[video-player] video.js patch already applied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!source.includes(originalSnippet)) {
|
||||||
|
throw new Error(
|
||||||
|
"[video-player] Cannot apply video.js patch: target snippet not found. Expected video.js 8.23.4 source."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const patched = source.replace(originalSnippet, patchedSnippet);
|
||||||
|
writeFileSync(videoEsPath, patched, "utf8");
|
||||||
|
console.log("[video-player] Applied video.js patch");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
run();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error instanceof Error ? error.message : String(error));
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
@@ -143,8 +143,12 @@ const detectIOS = () => {
|
|||||||
|
|
||||||
const createAuthPlaylistLoader = ({
|
const createAuthPlaylistLoader = ({
|
||||||
debug,
|
debug,
|
||||||
|
getToken,
|
||||||
|
refreshToken,
|
||||||
}: {
|
}: {
|
||||||
debug?: boolean;
|
debug?: boolean;
|
||||||
|
getToken: () => string | null;
|
||||||
|
refreshToken: () => void;
|
||||||
}): PlaylistLoaderConstructor => {
|
}): PlaylistLoaderConstructor => {
|
||||||
const BaseLoader = Hls.DefaultConfig.loader as unknown as new (
|
const BaseLoader = Hls.DefaultConfig.loader as unknown as new (
|
||||||
config: HlsConfig,
|
config: HlsConfig,
|
||||||
@@ -155,37 +159,31 @@ const createAuthPlaylistLoader = ({
|
|||||||
super({ ...config, debug: debug ?? false });
|
super({ ...config, debug: debug ?? false });
|
||||||
}
|
}
|
||||||
|
|
||||||
load(
|
override load(
|
||||||
context: PlaylistLoaderContext,
|
context: PlaylistLoaderContext,
|
||||||
config: LoaderConfiguration,
|
config: LoaderConfiguration,
|
||||||
callbacks: LoaderCallbacks<PlaylistLoaderContext>,
|
callbacks: LoaderCallbacks<PlaylistLoaderContext>,
|
||||||
): void {
|
): void {
|
||||||
const start = async () => {
|
try {
|
||||||
try {
|
const token = getToken();
|
||||||
const token = await resolveVideoPlayerToken();
|
if (token) {
|
||||||
if (token) {
|
context.headers = {
|
||||||
context.headers = {
|
...(context.headers ?? {}),
|
||||||
...(context.headers ?? {}),
|
Authorization: `Bearer ${token}`,
|
||||||
Authorization: `Bearer ${token}`,
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
if (debug) {
|
|
||||||
console.warn(
|
|
||||||
"[VideoRuntime:HLS] Failed to append auth header to playlist request",
|
|
||||||
error,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
super.load(context, config, callbacks);
|
|
||||||
}
|
}
|
||||||
};
|
} catch (error) {
|
||||||
|
|
||||||
void start().catch(error => {
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.error("[VideoRuntime:HLS] Playlist loader start failed", error);
|
console.warn(
|
||||||
|
"[VideoRuntime:HLS] Failed to append auth header to playlist request",
|
||||||
|
error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
// Critical path must stay sync for hls.js loader lifecycle.
|
||||||
|
super.load(context, config, callbacks);
|
||||||
|
refreshToken();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -232,6 +230,8 @@ export class VideoPlayerRuntime {
|
|||||||
private currentEngine: PlaybackEngine | null = null;
|
private currentEngine: PlaybackEngine | null = null;
|
||||||
private currentSource: VideoPlayerRuntimeSource | null = null;
|
private currentSource: VideoPlayerRuntimeSource | null = null;
|
||||||
private vhsAuthTokenRef: string | null | undefined = null;
|
private vhsAuthTokenRef: string | null | undefined = null;
|
||||||
|
private hlsAuthTokenRef: string | null = null;
|
||||||
|
private hlsTokenResolvePromise: Promise<void> | null = null;
|
||||||
private vhsRequestCleanupRef: (() => void) | null = null;
|
private vhsRequestCleanupRef: (() => void) | null = null;
|
||||||
private visibilityObserverRef: IntersectionObserver | null = null;
|
private visibilityObserverRef: IntersectionObserver | null = null;
|
||||||
private originalPlayRef: VideoPlayerRuntimePlayer["play"] | null = null;
|
private originalPlayRef: VideoPlayerRuntimePlayer["play"] | null = null;
|
||||||
@@ -328,6 +328,8 @@ export class VideoPlayerRuntime {
|
|||||||
this.vhsRequestCleanupRef?.();
|
this.vhsRequestCleanupRef?.();
|
||||||
this.vhsRequestCleanupRef = null;
|
this.vhsRequestCleanupRef = null;
|
||||||
this.vhsAuthTokenRef = null;
|
this.vhsAuthTokenRef = null;
|
||||||
|
this.hlsAuthTokenRef = null;
|
||||||
|
this.hlsTokenResolvePromise = null;
|
||||||
|
|
||||||
if (this.playerRef) {
|
if (this.playerRef) {
|
||||||
this.playerRef.dispose();
|
this.playerRef.dispose();
|
||||||
@@ -358,6 +360,34 @@ export class VideoPlayerRuntime {
|
|||||||
return this.playerRef;
|
return this.playerRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async ensureHlsAuthToken(): Promise<void> {
|
||||||
|
if (this.hlsTokenResolvePromise !== null) {
|
||||||
|
await this.hlsTokenResolvePromise;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hlsTokenResolvePromise = resolveVideoPlayerToken()
|
||||||
|
.then(token => {
|
||||||
|
this.hlsAuthTokenRef = token ?? null;
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.hlsAuthTokenRef = null;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.hlsTokenResolvePromise = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.hlsTokenResolvePromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
private refreshHlsAuthTokenInBackground(): void {
|
||||||
|
if (this.hlsTokenResolvePromise !== null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void this.ensureHlsAuthToken();
|
||||||
|
}
|
||||||
|
|
||||||
private emit<K extends keyof VideoPlayerRuntimeEventMap>(
|
private emit<K extends keyof VideoPlayerRuntimeEventMap>(
|
||||||
event: K,
|
event: K,
|
||||||
payload: VideoPlayerRuntimeEventMap[K],
|
payload: VideoPlayerRuntimeEventMap[K],
|
||||||
@@ -658,7 +688,11 @@ export class VideoPlayerRuntime {
|
|||||||
? { abrEwmaDefaultEstimate: 10690560 * 1.2 }
|
? { abrEwmaDefaultEstimate: 10690560 * 1.2 }
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
const playlistLoader = createAuthPlaylistLoader({ debug: options.debug });
|
const playlistLoader = createAuthPlaylistLoader({
|
||||||
|
debug: options.debug,
|
||||||
|
getToken: () => this.hlsAuthTokenRef,
|
||||||
|
refreshToken: () => this.refreshHlsAuthTokenInBackground(),
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
debug: options.debug,
|
debug: options.debug,
|
||||||
@@ -702,6 +736,9 @@ export class VideoPlayerRuntime {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resolve async token before starting HLS manifest load.
|
||||||
|
await this.ensureHlsAuthToken();
|
||||||
|
|
||||||
const setupHls = () => {
|
const setupHls = () => {
|
||||||
if (this.hlsLoaded) {
|
if (this.hlsLoaded) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user