mirror of
https://github.com/zoriya/react-native-video.git
synced 2025-12-05 23:06:14 +00:00
Some cleanup
This commit is contained in:
@@ -17,12 +17,16 @@ import { WebEventEmiter } from "./WebEventEmiter";
|
||||
class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
protected player = new shaka.Player();
|
||||
protected video: HTMLVideoElement;
|
||||
protected headers: Record<string, string> = {};
|
||||
|
||||
constructor(source: VideoSource | VideoConfig | VideoPlayerSource) {
|
||||
const video = document.createElement("video");
|
||||
super(new WebEventEmiter(video));
|
||||
this.video = video;
|
||||
this.player.attach(this.video);
|
||||
this.player.getNetworkingEngine()!.registerRequestFilter((_type, request) => {
|
||||
request.headers = this.headers;
|
||||
});
|
||||
this.replaceSourceAsync(source);
|
||||
}
|
||||
|
||||
@@ -59,7 +63,10 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
|
||||
// Source
|
||||
get source(): VideoPlayerSource {
|
||||
return this.player.source;
|
||||
return {
|
||||
uri: this.player.getAssetUri()!,
|
||||
config: {},
|
||||
};
|
||||
}
|
||||
|
||||
// Status
|
||||
@@ -155,30 +162,38 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
set playInBackground(value: boolean) {
|
||||
this.player.playInBackground = value;
|
||||
set playInBackground(_: boolean) {
|
||||
if (__DEV__) {
|
||||
console.warn(
|
||||
"playInBackground is not supported on this platform, it wont have any effect",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Play When Inactive
|
||||
get playWhenInactive(): boolean {
|
||||
return this.player.playWhenInactive;
|
||||
return true;
|
||||
}
|
||||
|
||||
set playWhenInactive(value: boolean) {
|
||||
this.player.playWhenInactive = value;
|
||||
set playWhenInactive(_: boolean) {
|
||||
if (__DEV__) {
|
||||
console.warn(
|
||||
"playWhenInactive is not supported on this platform, it wont have any effect",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Is Playing
|
||||
get isPlaying(): boolean {
|
||||
return this.player.isPlaying;
|
||||
return this.status === "readyToPlay" && !this.video.paused;
|
||||
}
|
||||
|
||||
async initialize(): Promise<void> {
|
||||
await this.wrapPromise(this.player.initialize());
|
||||
// noop on web
|
||||
}
|
||||
|
||||
async preload(): Promise<void> {
|
||||
this.player.load(this.media, this.startTime);
|
||||
// we start loading when initializing the source.
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,33 +245,49 @@ class VideoPlayer extends VideoPlayerEvents implements VideoPlayerBase {
|
||||
| NoAutocomplete<VideoPlayerSource>
|
||||
| null,
|
||||
): Promise<void> {
|
||||
this.video.src =
|
||||
typeof source === "object" && "uri" in source
|
||||
const src =
|
||||
typeof source === "object" && source && "uri" in source
|
||||
? source.uri
|
||||
: source;
|
||||
if (typeof src === "number") {
|
||||
console.error("A source uri must be a string. Numbers are only supported on native.");
|
||||
return;
|
||||
}
|
||||
// TODO: handle start time
|
||||
this.player.load(src)
|
||||
if (typeof source !== "object") return;
|
||||
|
||||
this.headers = source?.headers ?? {};
|
||||
// this.player.configure({
|
||||
// drm: undefined,
|
||||
// streaming: {
|
||||
// bufferingGoal: source?.bufferConfig?.maxBufferMs,
|
||||
// },
|
||||
// } satisfies Partial<shaka.extern.PlayerConfiguration>);
|
||||
}
|
||||
|
||||
// Text Track Management
|
||||
getAvailableTextTracks(): TextTrack[] {
|
||||
try {
|
||||
return this.player.getAvailableTextTracks();
|
||||
} catch (error) {
|
||||
this.throwError(error);
|
||||
return [];
|
||||
}
|
||||
return this.player.getTextTracks().map(x => ({
|
||||
id: x.id.toString(),
|
||||
label: x.label ?? "",
|
||||
language: x.language,
|
||||
selected: x.active,
|
||||
}));
|
||||
}
|
||||
|
||||
selectTextTrack(textTrack: TextTrack | null): void {
|
||||
try {
|
||||
this.player.selectTextTrack(textTrack);
|
||||
} catch (error) {
|
||||
this.throwError(error);
|
||||
}
|
||||
this.player.setTextTrackVisibility(textTrack !== null)
|
||||
if (!textTrack) return;
|
||||
const track = this.player
|
||||
.getTextTracks()
|
||||
.find((x) => x.id === Number(textTrack.id));
|
||||
if (track) this.player.selectTextTrack(track);
|
||||
}
|
||||
|
||||
// Selected Text Track
|
||||
get selectedTrack(): TextTrack | undefined {
|
||||
return this.player.selectedTrack;
|
||||
return this.getAvailableTextTracks().find(x => x.selected);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type { VideoPlayerEventEmitter } from '../spec/nitro/VideoPlayerEventEmitter.nitro';
|
||||
import {
|
||||
ALL_PLAYER_EVENTS,
|
||||
type AllPlayerEvents as PlayerEvents,
|
||||
} from './types/Events';
|
||||
|
||||
export class VideoPlayerEvents {
|
||||
protected eventEmitter: VideoPlayerEventEmitter;
|
||||
protected eventEmitter: PlayerEvents;
|
||||
protected eventListeners: Partial<
|
||||
Record<keyof PlayerEvents, Set<(...params: any[]) => void>>
|
||||
> = {};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { NoAutocomplete } from '../types/Utils';
|
||||
import type { VideoConfig, VideoSource } from '../types/VideoConfig';
|
||||
import { isVideoPlayerSource } from '../utils/sourceFactory';
|
||||
import { isVideoPlayerSource } from '../utils/sourceUtils';
|
||||
import { VideoPlayer } from '../VideoPlayer';
|
||||
import { useManagedInstance } from './useManagedInstance';
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { NoAutocomplete } from '../types/Utils';
|
||||
import type { VideoConfig, VideoSource } from '../types/VideoConfig';
|
||||
import { isVideoPlayerSource } from '../utils/sourceFactory';
|
||||
import { VideoPlayer } from '../VideoPlayer';
|
||||
import { useManagedInstance } from './useManagedInstance';
|
||||
|
||||
const sourceEqual = <T extends VideoConfig | VideoSource | VideoPlayerSource>(
|
||||
a: T,
|
||||
b?: T
|
||||
) => {
|
||||
if (isVideoPlayerSource(a) && isVideoPlayerSource(b)) {
|
||||
return a.equals(b);
|
||||
}
|
||||
|
||||
return JSON.stringify(a) === JSON.stringify(b);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a `VideoPlayer` instance and manages its lifecycle.
|
||||
*
|
||||
* @param source - The source of the video to play
|
||||
* @param setup - A function to setup the player
|
||||
* @returns The `VideoPlayer` instance
|
||||
*/
|
||||
export const useVideoPlayer = (
|
||||
source: VideoConfig | VideoSource | NoAutocomplete<VideoPlayerSource>,
|
||||
setup?: (player: VideoPlayer) => void
|
||||
) => {
|
||||
return useManagedInstance(
|
||||
{
|
||||
factory: () => {
|
||||
const player = new VideoPlayer(source);
|
||||
setup?.(player);
|
||||
return player;
|
||||
},
|
||||
cleanup: (player) => {
|
||||
player.__destroy();
|
||||
},
|
||||
dependenciesEqualFn: sourceEqual,
|
||||
},
|
||||
[JSON.stringify(source)]
|
||||
);
|
||||
};
|
||||
@@ -5,8 +5,9 @@ import type {
|
||||
} from '../../spec/nitro/VideoPlayer.nitro';
|
||||
import type { VideoPlayerSource } from '../../spec/nitro/VideoPlayerSource.nitro';
|
||||
import type { VideoConfig, VideoSource } from '../types/VideoConfig';
|
||||
import { createSource, isVideoPlayerSource } from './sourceFactory';
|
||||
import { createSource } from './sourceFactory';
|
||||
import { tryParseNativeVideoError } from '../types/VideoError';
|
||||
import { isVideoPlayerSource } from './sourceUtils';
|
||||
|
||||
const VideoPlayerFactory =
|
||||
NitroModules.createHybridObject<VideoPlayerFactory>('VideoPlayerFactory');
|
||||
|
||||
@@ -12,21 +12,13 @@ import type {
|
||||
VideoSource,
|
||||
} from '../types/VideoConfig';
|
||||
import { tryParseNativeVideoError } from '../types/VideoError';
|
||||
import { isVideoPlayerSource } from './sourceUtils';
|
||||
|
||||
const VideoPlayerSourceFactory =
|
||||
NitroModules.createHybridObject<VideoPlayerSourceFactory>(
|
||||
'VideoPlayerSourceFactory'
|
||||
);
|
||||
|
||||
export const isVideoPlayerSource = (obj: any): obj is VideoPlayerSource => {
|
||||
return (
|
||||
obj && // obj is not null
|
||||
typeof obj === 'object' && // obj is an object
|
||||
'name' in obj && // obj has a name property
|
||||
obj.name === 'VideoPlayerSource' // obj.name is 'VideoPlayerSource'
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a `VideoPlayerSource` instance from a URI (string).
|
||||
*
|
||||
|
||||
11
packages/react-native-video/src/core/utils/sourceUtils.ts
Normal file
11
packages/react-native-video/src/core/utils/sourceUtils.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import type { VideoPlayerSource } from "../../spec/nitro/VideoPlayerSource.nitro";
|
||||
|
||||
export const isVideoPlayerSource = (obj: any): obj is VideoPlayerSource => {
|
||||
return (
|
||||
obj && // obj is not null
|
||||
typeof obj === 'object' && // obj is an object
|
||||
'name' in obj && // obj has a name property
|
||||
obj.name === 'VideoPlayerSource' // obj.name is 'VideoPlayerSource'
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user