expo-video 1.1.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/android/build.gradle +2 -2
- package/build/VideoPlayer.d.ts +8 -0
- package/build/VideoPlayer.d.ts.map +1 -0
- package/build/VideoPlayer.js +16 -0
- package/build/VideoPlayer.js.map +1 -0
- package/build/VideoPlayer.web.d.ts +42 -0
- package/build/VideoPlayer.web.d.ts.map +1 -0
- package/build/VideoPlayer.web.js +230 -0
- package/build/VideoPlayer.web.js.map +1 -0
- package/build/VideoView.d.ts +1 -7
- package/build/VideoView.d.ts.map +1 -1
- package/build/VideoView.js +0 -14
- package/build/VideoView.js.map +1 -1
- package/build/VideoView.web.d.ts +2 -38
- package/build/VideoView.web.d.ts.map +1 -1
- package/build/VideoView.web.js +40 -241
- package/build/VideoView.web.js.map +1 -1
- package/build/index.d.ts +2 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/build/index.js.map +1 -1
- package/ios/VideoView.swift +4 -0
- package/package.json +2 -2
- package/src/VideoPlayer.tsx +22 -0
- package/src/VideoPlayer.web.tsx +278 -0
- package/src/VideoView.tsx +1 -20
- package/src/VideoView.web.tsx +46 -284
- package/src/index.ts +2 -1
package/CHANGELOG.md
CHANGED
package/android/build.gradle
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
apply plugin: 'com.android.library'
|
|
2
2
|
|
|
3
3
|
group = 'host.exp.exponent'
|
|
4
|
-
version = '1.1.
|
|
4
|
+
version = '1.1.2'
|
|
5
5
|
|
|
6
6
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
7
|
apply from: expoModulesCorePlugin
|
|
@@ -14,7 +14,7 @@ android {
|
|
|
14
14
|
namespace "expo.modules.video"
|
|
15
15
|
defaultConfig {
|
|
16
16
|
versionCode 1
|
|
17
|
-
versionName '1.1.
|
|
17
|
+
versionName '1.1.2'
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { VideoPlayer, VideoSource } from './VideoView.types';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
4
|
+
* @param source - A video source that is used to initialize the player.
|
|
5
|
+
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
8
|
+
//# sourceMappingURL=VideoPlayer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoPlayer.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACpC,WAAW,CAQb"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useReleasingSharedObject } from 'expo-modules-core';
|
|
2
|
+
import NativeVideoModule from './NativeVideoModule';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
5
|
+
* @param source - A video source that is used to initialize the player.
|
|
6
|
+
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
7
|
+
*/
|
|
8
|
+
export function useVideoPlayer(source, setup) {
|
|
9
|
+
const parsedSource = typeof source === 'string' ? { uri: source } : source;
|
|
10
|
+
return useReleasingSharedObject(() => {
|
|
11
|
+
const player = new NativeVideoModule.VideoPlayer(parsedSource);
|
|
12
|
+
setup?.(player);
|
|
13
|
+
return player;
|
|
14
|
+
}, [JSON.stringify(parsedSource)]);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=VideoPlayer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoPlayer.js","sourceRoot":"","sources":["../src/VideoPlayer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAGpD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAmB,EACnB,KAAqC;IAErC,MAAM,YAAY,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAE3E,OAAO,wBAAwB,CAAC,GAAG,EAAE;QACnC,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;QAC/D,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;QAChB,OAAO,MAAM,CAAC;IAChB,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACrC,CAAC","sourcesContent":["import { useReleasingSharedObject } from 'expo-modules-core';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport { VideoPlayer, VideoSource } from './VideoView.types';\n\n/**\n * Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.\n * @param source - A video source that is used to initialize the player.\n * @param setup - A function that allows setting up the player. It will run after the player is created.\n */\nexport function useVideoPlayer(\n source: VideoSource,\n setup?: (player: VideoPlayer) => void\n): VideoPlayer {\n const parsedSource = typeof source === 'string' ? { uri: source } : source;\n\n return useReleasingSharedObject(() => {\n const player = new NativeVideoModule.VideoPlayer(parsedSource);\n setup?.(player);\n return player;\n }, [JSON.stringify(parsedSource)]);\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { VideoPlayer, VideoPlayerEvents, VideoPlayerStatus, VideoSource } from './VideoView.types';
|
|
2
|
+
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
3
|
+
export declare function getSourceUri(source: VideoSource): string | null;
|
|
4
|
+
export declare class VideoPlayerWeb extends globalThis.expo.SharedObject<VideoPlayerEvents> implements VideoPlayer {
|
|
5
|
+
constructor(source: VideoSource);
|
|
6
|
+
src: VideoSource;
|
|
7
|
+
_mountedVideos: Set<HTMLVideoElement>;
|
|
8
|
+
_audioNodes: Set<MediaElementAudioSourceNode>;
|
|
9
|
+
playing: boolean;
|
|
10
|
+
_muted: boolean;
|
|
11
|
+
_volume: number;
|
|
12
|
+
_loop: boolean;
|
|
13
|
+
_playbackRate: number;
|
|
14
|
+
_preservesPitch: boolean;
|
|
15
|
+
_status: VideoPlayerStatus;
|
|
16
|
+
staysActiveInBackground: boolean;
|
|
17
|
+
set muted(value: boolean);
|
|
18
|
+
get muted(): boolean;
|
|
19
|
+
set playbackRate(value: number);
|
|
20
|
+
get playbackRate(): number;
|
|
21
|
+
set volume(value: number);
|
|
22
|
+
get volume(): number;
|
|
23
|
+
set loop(value: boolean);
|
|
24
|
+
get loop(): boolean;
|
|
25
|
+
get currentTime(): number;
|
|
26
|
+
set currentTime(value: number);
|
|
27
|
+
get preservesPitch(): boolean;
|
|
28
|
+
set preservesPitch(value: boolean);
|
|
29
|
+
get status(): VideoPlayerStatus;
|
|
30
|
+
mountVideoView(video: HTMLVideoElement): void;
|
|
31
|
+
unmountVideoView(video: HTMLVideoElement): void;
|
|
32
|
+
mountAudioNode(audioContext: AudioContext, zeroGainNode: GainNode, audioSourceNode: MediaElementAudioSourceNode): void;
|
|
33
|
+
unmountAudioNode(video: HTMLVideoElement, audioContext: AudioContext, audioSourceNode: MediaElementAudioSourceNode): void;
|
|
34
|
+
play(): void;
|
|
35
|
+
pause(): void;
|
|
36
|
+
replace(source: VideoSource): void;
|
|
37
|
+
seekBy(seconds: number): void;
|
|
38
|
+
replay(): void;
|
|
39
|
+
_synchronizeWithFirstVideo(video: HTMLVideoElement): void;
|
|
40
|
+
_addListeners(video: HTMLVideoElement): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=VideoPlayer.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoPlayer.web.d.ts","sourceRoot":"","sources":["../src/VideoPlayer.web.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEnG,wBAAgB,cAAc,CAC5B,MAAM,EAAE,WAAW,EACnB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,GACpC,WAAW,CAQb;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAK/D;AAED,qBAAa,cACX,SAAQ,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,iBAAiB,CACtD,YAAW,WAAW;gBAEV,MAAM,EAAE,WAAW;IAK/B,GAAG,EAAE,WAAW,CAAQ;IACxB,cAAc,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAa;IAClD,WAAW,EAAE,GAAG,CAAC,2BAA2B,CAAC,CAAa;IAC1D,OAAO,EAAE,OAAO,CAAS;IACzB,MAAM,EAAE,OAAO,CAAS;IACxB,OAAO,EAAE,MAAM,CAAK;IACpB,KAAK,EAAE,OAAO,CAAS;IACvB,aAAa,EAAE,MAAM,CAAO;IAC5B,eAAe,EAAE,OAAO,CAAQ;IAChC,OAAO,EAAE,iBAAiB,CAAU;IACpC,uBAAuB,EAAE,OAAO,CAAS;IAEzC,IAAI,KAAK,CAAC,KAAK,EAAE,OAAO,EAKvB;IAED,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,EAI7B;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,MAAM,EAKvB;IAED,IAAI,MAAM,IAAI,MAAM,CAKnB;IAED,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAKtB;IAED,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,IAAI,WAAW,IAAI,MAAM,CAGxB;IAED,IAAI,WAAW,CAAC,KAAK,EAAE,MAAM,EAI5B;IAED,IAAI,cAAc,IAAI,OAAO,CAE5B;IAED,IAAI,cAAc,CAAC,KAAK,EAAE,OAAO,EAKhC;IAED,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAED,cAAc,CAAC,KAAK,EAAE,gBAAgB;IAMtC,gBAAgB,CAAC,KAAK,EAAE,gBAAgB;IAIxC,cAAc,CACZ,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,QAAQ,EACtB,eAAe,EAAE,2BAA2B,GAC3C,IAAI;IAYP,gBAAgB,CACd,KAAK,EAAE,gBAAgB,EACvB,YAAY,EAAE,YAAY,EAC1B,eAAe,EAAE,2BAA2B;IAe9C,IAAI,IAAI,IAAI;IAOZ,KAAK,IAAI,IAAI;IAOb,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAelC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM7B,MAAM,IAAI,IAAI;IAQd,0BAA0B,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;IAezD,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI;CA0D7C"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
export function useVideoPlayer(source, setup) {
|
|
3
|
+
const parsedSource = typeof source === 'string' ? { uri: source } : source;
|
|
4
|
+
return useMemo(() => {
|
|
5
|
+
const player = new VideoPlayerWeb(parsedSource);
|
|
6
|
+
setup?.(player);
|
|
7
|
+
return player;
|
|
8
|
+
}, [JSON.stringify(source)]);
|
|
9
|
+
}
|
|
10
|
+
export function getSourceUri(source) {
|
|
11
|
+
if (typeof source == 'string') {
|
|
12
|
+
return source;
|
|
13
|
+
}
|
|
14
|
+
return source?.uri ?? null;
|
|
15
|
+
}
|
|
16
|
+
export class VideoPlayerWeb extends globalThis.expo.SharedObject {
|
|
17
|
+
constructor(source) {
|
|
18
|
+
super();
|
|
19
|
+
this.src = source;
|
|
20
|
+
}
|
|
21
|
+
src = null;
|
|
22
|
+
_mountedVideos = new Set();
|
|
23
|
+
_audioNodes = new Set();
|
|
24
|
+
playing = false;
|
|
25
|
+
_muted = false;
|
|
26
|
+
_volume = 1;
|
|
27
|
+
_loop = false;
|
|
28
|
+
_playbackRate = 1.0;
|
|
29
|
+
_preservesPitch = true;
|
|
30
|
+
_status = 'idle';
|
|
31
|
+
staysActiveInBackground = false; // Not supported on web. Dummy to match the interface.
|
|
32
|
+
set muted(value) {
|
|
33
|
+
this._mountedVideos.forEach((video) => {
|
|
34
|
+
video.muted = value;
|
|
35
|
+
});
|
|
36
|
+
this._muted = value;
|
|
37
|
+
}
|
|
38
|
+
get muted() {
|
|
39
|
+
return this._muted;
|
|
40
|
+
}
|
|
41
|
+
set playbackRate(value) {
|
|
42
|
+
this._mountedVideos.forEach((video) => {
|
|
43
|
+
video.playbackRate = value;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
get playbackRate() {
|
|
47
|
+
return this._playbackRate;
|
|
48
|
+
}
|
|
49
|
+
set volume(value) {
|
|
50
|
+
this._mountedVideos.forEach((video) => {
|
|
51
|
+
video.volume = value;
|
|
52
|
+
});
|
|
53
|
+
this._volume = value;
|
|
54
|
+
}
|
|
55
|
+
get volume() {
|
|
56
|
+
this._mountedVideos.forEach((video) => {
|
|
57
|
+
this._volume = video.volume;
|
|
58
|
+
});
|
|
59
|
+
return this._volume;
|
|
60
|
+
}
|
|
61
|
+
set loop(value) {
|
|
62
|
+
this._mountedVideos.forEach((video) => {
|
|
63
|
+
video.loop = value;
|
|
64
|
+
});
|
|
65
|
+
this._loop = value;
|
|
66
|
+
}
|
|
67
|
+
get loop() {
|
|
68
|
+
return this._loop;
|
|
69
|
+
}
|
|
70
|
+
get currentTime() {
|
|
71
|
+
// All videos should be synchronized, so we return the position of the first video.
|
|
72
|
+
return [...this._mountedVideos][0].currentTime;
|
|
73
|
+
}
|
|
74
|
+
set currentTime(value) {
|
|
75
|
+
this._mountedVideos.forEach((video) => {
|
|
76
|
+
video.currentTime = value;
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
get preservesPitch() {
|
|
80
|
+
return this._preservesPitch;
|
|
81
|
+
}
|
|
82
|
+
set preservesPitch(value) {
|
|
83
|
+
this._mountedVideos.forEach((video) => {
|
|
84
|
+
video.preservesPitch = value;
|
|
85
|
+
});
|
|
86
|
+
this._preservesPitch = value;
|
|
87
|
+
}
|
|
88
|
+
get status() {
|
|
89
|
+
return this._status;
|
|
90
|
+
}
|
|
91
|
+
mountVideoView(video) {
|
|
92
|
+
this._mountedVideos.add(video);
|
|
93
|
+
this._addListeners(video);
|
|
94
|
+
this._synchronizeWithFirstVideo(video);
|
|
95
|
+
}
|
|
96
|
+
unmountVideoView(video) {
|
|
97
|
+
this._mountedVideos.delete(video);
|
|
98
|
+
}
|
|
99
|
+
mountAudioNode(audioContext, zeroGainNode, audioSourceNode) {
|
|
100
|
+
if (!audioContext || !zeroGainNode)
|
|
101
|
+
return;
|
|
102
|
+
this._audioNodes.add(audioSourceNode);
|
|
103
|
+
// First mounted video should be connected to the audio context. All other videos have to be muted.
|
|
104
|
+
if (this._audioNodes.size === 1) {
|
|
105
|
+
audioSourceNode.connect(audioContext.destination);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
audioSourceNode.connect(zeroGainNode);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
unmountAudioNode(video, audioContext, audioSourceNode) {
|
|
112
|
+
const mountedVideos = [...this._mountedVideos];
|
|
113
|
+
const videoPlayingAudio = mountedVideos[0];
|
|
114
|
+
this._audioNodes.delete(audioSourceNode);
|
|
115
|
+
audioSourceNode.disconnect();
|
|
116
|
+
// If video playing audio has been removed, select a new video to be the audio player by disconnecting it from the mute node.
|
|
117
|
+
if (videoPlayingAudio === video && this._audioNodes.size > 0 && audioContext) {
|
|
118
|
+
const newMainAudioSource = [...this._audioNodes][0];
|
|
119
|
+
newMainAudioSource.disconnect();
|
|
120
|
+
newMainAudioSource.connect(audioContext.destination);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
play() {
|
|
124
|
+
this._mountedVideos.forEach((video) => {
|
|
125
|
+
video.play();
|
|
126
|
+
});
|
|
127
|
+
this.playing = true;
|
|
128
|
+
}
|
|
129
|
+
pause() {
|
|
130
|
+
this._mountedVideos.forEach((video) => {
|
|
131
|
+
video.pause();
|
|
132
|
+
});
|
|
133
|
+
this.playing = false;
|
|
134
|
+
}
|
|
135
|
+
replace(source) {
|
|
136
|
+
this._mountedVideos.forEach((video) => {
|
|
137
|
+
const uri = getSourceUri(source);
|
|
138
|
+
video.pause();
|
|
139
|
+
if (uri) {
|
|
140
|
+
video.setAttribute('src', uri);
|
|
141
|
+
video.load();
|
|
142
|
+
video.play();
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
video.removeAttribute('src');
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
this.playing = true;
|
|
149
|
+
}
|
|
150
|
+
seekBy(seconds) {
|
|
151
|
+
this._mountedVideos.forEach((video) => {
|
|
152
|
+
video.currentTime += seconds;
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
replay() {
|
|
156
|
+
this._mountedVideos.forEach((video) => {
|
|
157
|
+
video.currentTime = 0;
|
|
158
|
+
video.play();
|
|
159
|
+
});
|
|
160
|
+
this.playing = true;
|
|
161
|
+
}
|
|
162
|
+
_synchronizeWithFirstVideo(video) {
|
|
163
|
+
const firstVideo = [...this._mountedVideos][0];
|
|
164
|
+
if (!firstVideo)
|
|
165
|
+
return;
|
|
166
|
+
if (firstVideo.paused) {
|
|
167
|
+
video.pause();
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
video.play();
|
|
171
|
+
}
|
|
172
|
+
video.currentTime = firstVideo.currentTime;
|
|
173
|
+
video.volume = firstVideo.volume;
|
|
174
|
+
video.muted = firstVideo.muted;
|
|
175
|
+
video.playbackRate = firstVideo.playbackRate;
|
|
176
|
+
}
|
|
177
|
+
_addListeners(video) {
|
|
178
|
+
video.onplay = () => {
|
|
179
|
+
this.playing = true;
|
|
180
|
+
this._mountedVideos.forEach((mountedVideo) => {
|
|
181
|
+
mountedVideo.play();
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
video.onpause = () => {
|
|
185
|
+
this.playing = false;
|
|
186
|
+
this._mountedVideos.forEach((mountedVideo) => {
|
|
187
|
+
mountedVideo.pause();
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
video.onvolumechange = () => {
|
|
191
|
+
this.volume = video.volume;
|
|
192
|
+
this.muted = video.muted;
|
|
193
|
+
};
|
|
194
|
+
video.onseeking = () => {
|
|
195
|
+
this._mountedVideos.forEach((mountedVideo) => {
|
|
196
|
+
if (mountedVideo === video || mountedVideo.currentTime === video.currentTime)
|
|
197
|
+
return;
|
|
198
|
+
mountedVideo.currentTime = video.currentTime;
|
|
199
|
+
});
|
|
200
|
+
};
|
|
201
|
+
video.onseeked = () => {
|
|
202
|
+
this._mountedVideos.forEach((mountedVideo) => {
|
|
203
|
+
if (mountedVideo === video || mountedVideo.currentTime === video.currentTime)
|
|
204
|
+
return;
|
|
205
|
+
mountedVideo.currentTime = video.currentTime;
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
video.onratechange = () => {
|
|
209
|
+
this._mountedVideos.forEach((mountedVideo) => {
|
|
210
|
+
if (mountedVideo === video || mountedVideo.playbackRate === video.playbackRate)
|
|
211
|
+
return;
|
|
212
|
+
this._playbackRate = video.playbackRate;
|
|
213
|
+
mountedVideo.playbackRate = video.playbackRate;
|
|
214
|
+
});
|
|
215
|
+
};
|
|
216
|
+
video.onerror = () => {
|
|
217
|
+
this._status = 'error';
|
|
218
|
+
};
|
|
219
|
+
video.onloadeddata = () => {
|
|
220
|
+
this._status = 'readyToPlay';
|
|
221
|
+
if (this.playing && video.paused) {
|
|
222
|
+
video.play();
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
video.onwaiting = () => {
|
|
226
|
+
this._status = 'loading';
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=VideoPlayer.web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VideoPlayer.web.js","sourceRoot":"","sources":["../src/VideoPlayer.web.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo } from 'react';\n\nimport { VideoPlayer, VideoPlayerEvents, VideoPlayerStatus, VideoSource } from './VideoView.types';\n\nexport function useVideoPlayer(\n source: VideoSource,\n setup?: (player: VideoPlayer) => void\n): VideoPlayer {\n const parsedSource = typeof source === 'string' ? { uri: source } : source;\n\n return useMemo(() => {\n const player = new VideoPlayerWeb(parsedSource);\n setup?.(player);\n return player;\n }, [JSON.stringify(source)]);\n}\n\nexport function getSourceUri(source: VideoSource): string | null {\n if (typeof source == 'string') {\n return source;\n }\n return source?.uri ?? null;\n}\n\nexport class VideoPlayerWeb\n extends globalThis.expo.SharedObject<VideoPlayerEvents>\n implements VideoPlayer\n{\n constructor(source: VideoSource) {\n super();\n this.src = source;\n }\n\n src: VideoSource = null;\n _mountedVideos: Set<HTMLVideoElement> = new Set();\n _audioNodes: Set<MediaElementAudioSourceNode> = new Set();\n playing: boolean = false;\n _muted: boolean = false;\n _volume: number = 1;\n _loop: boolean = false;\n _playbackRate: number = 1.0;\n _preservesPitch: boolean = true;\n _status: VideoPlayerStatus = 'idle';\n staysActiveInBackground: boolean = false; // Not supported on web. Dummy to match the interface.\n\n set muted(value: boolean) {\n this._mountedVideos.forEach((video) => {\n video.muted = value;\n });\n this._muted = value;\n }\n\n get muted(): boolean {\n return this._muted;\n }\n\n set playbackRate(value: number) {\n this._mountedVideos.forEach((video) => {\n video.playbackRate = value;\n });\n }\n\n get playbackRate(): number {\n return this._playbackRate;\n }\n\n set volume(value: number) {\n this._mountedVideos.forEach((video) => {\n video.volume = value;\n });\n this._volume = value;\n }\n\n get volume(): number {\n this._mountedVideos.forEach((video) => {\n this._volume = video.volume;\n });\n return this._volume;\n }\n\n set loop(value: boolean) {\n this._mountedVideos.forEach((video) => {\n video.loop = value;\n });\n this._loop = value;\n }\n\n get loop(): boolean {\n return this._loop;\n }\n\n get currentTime(): number {\n // All videos should be synchronized, so we return the position of the first video.\n return [...this._mountedVideos][0].currentTime;\n }\n\n set currentTime(value: number) {\n this._mountedVideos.forEach((video) => {\n video.currentTime = value;\n });\n }\n\n get preservesPitch(): boolean {\n return this._preservesPitch;\n }\n\n set preservesPitch(value: boolean) {\n this._mountedVideos.forEach((video) => {\n video.preservesPitch = value;\n });\n this._preservesPitch = value;\n }\n\n get status(): VideoPlayerStatus {\n return this._status;\n }\n\n mountVideoView(video: HTMLVideoElement) {\n this._mountedVideos.add(video);\n this._addListeners(video);\n this._synchronizeWithFirstVideo(video);\n }\n\n unmountVideoView(video: HTMLVideoElement) {\n this._mountedVideos.delete(video);\n }\n\n mountAudioNode(\n audioContext: AudioContext,\n zeroGainNode: GainNode,\n audioSourceNode: MediaElementAudioSourceNode\n ): void {\n if (!audioContext || !zeroGainNode) return;\n\n this._audioNodes.add(audioSourceNode);\n // First mounted video should be connected to the audio context. All other videos have to be muted.\n if (this._audioNodes.size === 1) {\n audioSourceNode.connect(audioContext.destination);\n } else {\n audioSourceNode.connect(zeroGainNode);\n }\n }\n\n unmountAudioNode(\n video: HTMLVideoElement,\n audioContext: AudioContext,\n audioSourceNode: MediaElementAudioSourceNode\n ) {\n const mountedVideos = [...this._mountedVideos];\n const videoPlayingAudio = mountedVideos[0];\n this._audioNodes.delete(audioSourceNode);\n audioSourceNode.disconnect();\n\n // If video playing audio has been removed, select a new video to be the audio player by disconnecting it from the mute node.\n if (videoPlayingAudio === video && this._audioNodes.size > 0 && audioContext) {\n const newMainAudioSource = [...this._audioNodes][0];\n newMainAudioSource.disconnect();\n newMainAudioSource.connect(audioContext.destination);\n }\n }\n\n play(): void {\n this._mountedVideos.forEach((video) => {\n video.play();\n });\n this.playing = true;\n }\n\n pause(): void {\n this._mountedVideos.forEach((video) => {\n video.pause();\n });\n this.playing = false;\n }\n\n replace(source: VideoSource): void {\n this._mountedVideos.forEach((video) => {\n const uri = getSourceUri(source);\n video.pause();\n if (uri) {\n video.setAttribute('src', uri);\n video.load();\n video.play();\n } else {\n video.removeAttribute('src');\n }\n });\n this.playing = true;\n }\n\n seekBy(seconds: number): void {\n this._mountedVideos.forEach((video) => {\n video.currentTime += seconds;\n });\n }\n\n replay(): void {\n this._mountedVideos.forEach((video) => {\n video.currentTime = 0;\n video.play();\n });\n this.playing = true;\n }\n\n _synchronizeWithFirstVideo(video: HTMLVideoElement): void {\n const firstVideo = [...this._mountedVideos][0];\n if (!firstVideo) return;\n\n if (firstVideo.paused) {\n video.pause();\n } else {\n video.play();\n }\n video.currentTime = firstVideo.currentTime;\n video.volume = firstVideo.volume;\n video.muted = firstVideo.muted;\n video.playbackRate = firstVideo.playbackRate;\n }\n\n _addListeners(video: HTMLVideoElement): void {\n video.onplay = () => {\n this.playing = true;\n this._mountedVideos.forEach((mountedVideo) => {\n mountedVideo.play();\n });\n };\n\n video.onpause = () => {\n this.playing = false;\n this._mountedVideos.forEach((mountedVideo) => {\n mountedVideo.pause();\n });\n };\n\n video.onvolumechange = () => {\n this.volume = video.volume;\n this.muted = video.muted;\n };\n\n video.onseeking = () => {\n this._mountedVideos.forEach((mountedVideo) => {\n if (mountedVideo === video || mountedVideo.currentTime === video.currentTime) return;\n mountedVideo.currentTime = video.currentTime;\n });\n };\n\n video.onseeked = () => {\n this._mountedVideos.forEach((mountedVideo) => {\n if (mountedVideo === video || mountedVideo.currentTime === video.currentTime) return;\n mountedVideo.currentTime = video.currentTime;\n });\n };\n\n video.onratechange = () => {\n this._mountedVideos.forEach((mountedVideo) => {\n if (mountedVideo === video || mountedVideo.playbackRate === video.playbackRate) return;\n this._playbackRate = video.playbackRate;\n mountedVideo.playbackRate = video.playbackRate;\n });\n };\n\n video.onerror = () => {\n this._status = 'error';\n };\n\n video.onloadeddata = () => {\n this._status = 'readyToPlay';\n\n if (this.playing && video.paused) {\n video.play();\n }\n };\n\n video.onwaiting = () => {\n this._status = 'loading';\n };\n }\n}\n"]}
|
package/build/VideoView.d.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import { ReactNode, PureComponent } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
/**
|
|
4
|
-
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
5
|
-
* @param source - A video source that is used to initialize the player.
|
|
6
|
-
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
7
|
-
*/
|
|
8
|
-
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
2
|
+
import { VideoViewProps } from './VideoView.types';
|
|
9
3
|
/**
|
|
10
4
|
* Returns whether the current device supports Picture in Picture (PiP) mode.
|
|
11
5
|
* @returns A `boolean` which is `true` if the device supports PiP mode, and `false` otherwise.
|
package/build/VideoView.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VideoView.d.ts","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAI5D,OAAO,EAAe,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEhE;;;;;GAKG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAAC,OAAO,CAAC,CAE9D;AAED,qBAAa,SAAU,SAAQ,aAAa,CAAC,cAAc,CAAC;IAC1D,SAAS,iCAAoB;IAE7B;;OAEG;IACH,eAAe;IAIf;;OAEG;IACH,cAAc;IAId;;;;;OAKG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;;;OAIG;IACH,oBAAoB,IAAI,IAAI;IAI5B,MAAM,IAAI,SAAS;CAMpB"}
|
package/build/VideoView.js
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import { useReleasingSharedObject } from 'expo-modules-core';
|
|
2
1
|
import { PureComponent, createRef } from 'react';
|
|
3
2
|
import NativeVideoModule from './NativeVideoModule';
|
|
4
3
|
import NativeVideoView from './NativeVideoView';
|
|
5
|
-
/**
|
|
6
|
-
* Creates a `VideoPlayer`, which will be automatically cleaned up when the component is unmounted.
|
|
7
|
-
* @param source - A video source that is used to initialize the player.
|
|
8
|
-
* @param setup - A function that allows setting up the player. It will run after the player is created.
|
|
9
|
-
*/
|
|
10
|
-
export function useVideoPlayer(source, setup) {
|
|
11
|
-
const parsedSource = typeof source === 'string' ? { uri: source } : source;
|
|
12
|
-
return useReleasingSharedObject(() => {
|
|
13
|
-
const player = new NativeVideoModule.VideoPlayer(parsedSource);
|
|
14
|
-
setup?.(player);
|
|
15
|
-
return player;
|
|
16
|
-
}, [JSON.stringify(parsedSource)]);
|
|
17
|
-
}
|
|
18
4
|
/**
|
|
19
5
|
* Returns whether the current device supports Picture in Picture (PiP) mode.
|
|
20
6
|
* @returns A `boolean` which is `true` if the device supports PiP mode, and `false` otherwise.
|
package/build/VideoView.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoView.js","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"VideoView.js","sourceRoot":"","sources":["../src/VideoView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAE5D,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AACpD,OAAO,eAAe,MAAM,mBAAmB,CAAC;AAGhD;;;;;GAKG;AACH,MAAM,UAAU,2BAA2B;IACzC,OAAO,iBAAiB,CAAC,2BAA2B,EAAE,CAAC;AACzD,CAAC;AAED,MAAM,OAAO,SAAU,SAAQ,aAA6B;IAC1D,SAAS,GAAG,SAAS,EAAO,CAAC;IAE7B;;OAEG;IACH,eAAe;QACb,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,cAAc,EAAE,CAAC;IAC3C,CAAC;IAED;;;;;OAKG;IACH,qBAAqB;QACnB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,qBAAqB,EAAE,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACH,oBAAoB;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,oBAAoB,EAAE,CAAC;IACxD,CAAC;IAED,MAAM;QACJ,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC;QACxC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;QAErC,OAAO,CAAC,eAAe,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAG,CAAC;IAC/E,CAAC;CACF;AAED,gFAAgF;AAChF,gEAAgE;AAChE,yEAAyE;AACzE,SAAS,WAAW,CAAC,MAA4B;IAC/C,IAAI,MAAM,YAAY,iBAAiB,CAAC,WAAW,EAAE;QACnD,mBAAmB;QACnB,OAAO,MAAM,CAAC,yBAAyB,CAAC;KACzC;IACD,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QAC9B,OAAO,MAAM,CAAC;KACf;IACD,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { ReactNode, PureComponent, createRef } from 'react';\n\nimport NativeVideoModule from './NativeVideoModule';\nimport NativeVideoView from './NativeVideoView';\nimport { VideoPlayer, VideoViewProps } from './VideoView.types';\n\n/**\n * Returns whether the current device supports Picture in Picture (PiP) mode.\n * @returns A `boolean` which is `true` if the device supports PiP mode, and `false` otherwise.\n * @platform android\n * @platform ios\n */\nexport function isPictureInPictureSupported(): Promise<boolean> {\n return NativeVideoModule.isPictureInPictureSupported();\n}\n\nexport class VideoView extends PureComponent<VideoViewProps> {\n nativeRef = createRef<any>();\n\n /**\n * Enters fullscreen mode.\n */\n enterFullscreen() {\n this.nativeRef.current?.enterFullscreen();\n }\n\n /**\n * Exits fullscreen mode.\n */\n exitFullscreen() {\n this.nativeRef.current?.exitFullscreen();\n }\n\n /**\n * Enters Picture in Picture (PiP) mode. Throws an exception if the device does not support PiP.\n * > **Note:** Only one player can be in Picture in Picture (PiP) mode at a time.\n * @platform android\n * @platform ios 14+\n */\n startPictureInPicture(): void {\n return this.nativeRef.current?.startPictureInPicture();\n }\n\n /**\n * Exits Picture in Picture (PiP) mode.\n * @platform android\n * @platform ios 14+\n */\n stopPictureInPicture(): void {\n return this.nativeRef.current?.stopPictureInPicture();\n }\n\n render(): ReactNode {\n const { player, ...props } = this.props;\n const playerId = getPlayerId(player);\n\n return <NativeVideoView {...props} player={playerId} ref={this.nativeRef} />;\n }\n}\n\n// Temporary solution to pass the shared object ID instead of the player object.\n// We can't really pass it as an object in the old architecture.\n// Technically we can in the new architecture, but it's not possible yet.\nfunction getPlayerId(player: number | VideoPlayer): number | null {\n if (player instanceof NativeVideoModule.VideoPlayer) {\n // @ts-expect-error\n return player.__expo_shared_object_id__;\n }\n if (typeof player === 'number') {\n return player;\n }\n return null;\n}\n"]}
|
package/build/VideoView.web.d.ts
CHANGED
|
@@ -1,42 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
constructor(source: VideoSource);
|
|
5
|
-
src: VideoSource;
|
|
6
|
-
_mountedVideos: Set<HTMLVideoElement>;
|
|
7
|
-
_audioNodes: Set<MediaElementAudioSourceNode>;
|
|
8
|
-
playing: boolean;
|
|
9
|
-
_muted: boolean;
|
|
10
|
-
_volume: number;
|
|
11
|
-
_loop: boolean;
|
|
12
|
-
_playbackRate: number;
|
|
13
|
-
_preservesPitch: boolean;
|
|
14
|
-
_status: VideoPlayerStatus;
|
|
15
|
-
staysActiveInBackground: boolean;
|
|
16
|
-
set muted(value: boolean);
|
|
17
|
-
get muted(): boolean;
|
|
18
|
-
set playbackRate(value: number);
|
|
19
|
-
get playbackRate(): number;
|
|
20
|
-
set volume(value: number);
|
|
21
|
-
get volume(): number;
|
|
22
|
-
set loop(value: boolean);
|
|
23
|
-
get loop(): boolean;
|
|
24
|
-
get currentTime(): number;
|
|
25
|
-
set currentTime(value: number);
|
|
26
|
-
get preservesPitch(): boolean;
|
|
27
|
-
set preservesPitch(value: boolean);
|
|
28
|
-
get status(): VideoPlayerStatus;
|
|
29
|
-
mountVideoView(video: HTMLVideoElement): void;
|
|
30
|
-
unmountVideoView(video: HTMLVideoElement): void;
|
|
31
|
-
play(): void;
|
|
32
|
-
pause(): void;
|
|
33
|
-
replace(source: VideoSource): void;
|
|
34
|
-
seekBy(seconds: number): void;
|
|
35
|
-
replay(): void;
|
|
36
|
-
_synchronizeWithFirstVideo(video: HTMLVideoElement): void;
|
|
37
|
-
_addListeners(video: HTMLVideoElement): void;
|
|
38
|
-
}
|
|
39
|
-
export declare function useVideoPlayer(source: VideoSource, setup?: (player: VideoPlayer) => void): VideoPlayer;
|
|
2
|
+
import { VideoPlayerWeb } from './VideoPlayer.web';
|
|
3
|
+
import { VideoViewProps } from './VideoView.types';
|
|
40
4
|
export declare const VideoView: React.ForwardRefExoticComponent<{
|
|
41
5
|
player?: VideoPlayerWeb | undefined;
|
|
42
6
|
} & VideoViewProps & React.RefAttributes<unknown>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"VideoView.web.d.ts","sourceRoot":"","sources":["../src/VideoView.web.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA6D,MAAM,OAAO,CAAC;AAGlF,OAAO,EAAE,cAAc,EAAgB,MAAM,mBAAmB,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAsBnD,eAAO,MAAM,SAAS;;kDA6EpB,CAAC;AAEH,eAAe,SAAS,CAAC"}
|