feat: events callbacks & external subtitles (#9)

This commit is contained in:
Krzysztof Moch
2025-05-08 17:13:39 +02:00
committed by GitHub
parent e743c63a82
commit 742ddb3183
174 changed files with 9673 additions and 150 deletions
+2 -2
View File
@@ -1565,7 +1565,7 @@ PODS:
- React-logger (= 0.77.2)
- React-perflogger (= 0.77.2)
- React-utils (= 0.77.2)
- ReactNativeVideo (7.0.0-dev.0):
- ReactNativeVideo (7.0.0-dev.2):
- DoubleConversion
- glog
- hermes-engine
@@ -1876,7 +1876,7 @@ SPEC CHECKSUMS:
ReactAppDependencyProvider: f334cebc0beed0a72490492e978007082c03d533
ReactCodegen: 474fbb3e4bb0f1ee6c255d1955db76e13d509269
ReactCommon: 7763e59534d58e15f8f22121cdfe319040e08888
ReactNativeVideo: c92ba584a9c0b63a1ea48b990775d3773e58766e
ReactNativeVideo: 9fd7de1e0856a9d7843c3df42d33f610fd62caf1
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
Yoga: 31a098f74c16780569aebd614a0f37a907de0189
@@ -263,14 +263,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-frameworks.sh\"\n";
@@ -306,14 +302,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-VideoExample/Pods-VideoExample-resources.sh\"\n";
@@ -527,7 +519,10 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -596,7 +591,10 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../../node_modules/react-native";
SDKROOT = iphoneos;
USE_HERMES = true;
+75 -10
View File
@@ -14,6 +14,9 @@ import {
createSource,
useVideoPlayer,
VideoView,
type onLoadData,
type onProgressData,
type VideoPlayerStatus,
type VideoViewRef,
} from 'react-native-video';
@@ -33,10 +36,71 @@ const VideoDemo = () => {
const [loop, setLoop] = React.useState(false);
const [showNativeControls, setShowNativeControls] = React.useState(false);
// For demo: log last event
const [lastEvent, setLastEvent] = React.useState<string>('');
// View event handlers
const handleFullscreenChange = React.useCallback((fullscreen: boolean) => {
setLastEvent(
'View: onFullscreenChange ' + (fullscreen ? 'entered' : 'exited')
);
console.log('Fullscreen:', fullscreen);
}, []);
const handlePictureInPictureChange = React.useCallback(
(pipEnabled: boolean) => {
setLastEvent(
'View: onPictureInPictureChange ' + (pipEnabled ? 'entered' : 'exited')
);
console.log('PictureInPicture:', pipEnabled);
},
[]
);
const handlePlayerEnd = React.useCallback(() => {
setLastEvent('Player: onEnd');
console.log('Video has ended');
}, []);
const handlePlayerLoad = React.useCallback((data: onLoadData) => {
setLastEvent('Player: onLoad');
console.log('Video loaded', data);
}, []);
const handlePlayerBuffer = React.useCallback((buffering: boolean) => {
setLastEvent('Player: onBuffer ' + buffering);
console.log('Buffering:', buffering);
}, []);
const handlePlayerProgress = React.useCallback((data: onProgressData) => {
setProgress(data.currentTime);
}, []);
const handlePlayerStatusChange = React.useCallback(
(status: VideoPlayerStatus) => {
setLastEvent('Player: onStatusChange ' + status);
console.log('Status:', status);
},
[]
);
// Setup player and events
const player = useVideoPlayer(
'https://www.w3schools.com/html/mov_bbb.mp4',
{
uri: 'https://www.w3schools.com/html/movie.mp4',
externalSubtitles: [
{
uri: 'https://bitdash-a.akamaihd.net/content/sintel/subtitles/subtitles_en.vtt',
label: 'External',
},
],
},
(_player) => {
//_player.loop = loop;
_player.onEnd = handlePlayerEnd;
_player.onLoad = handlePlayerLoad;
_player.onBuffer = handlePlayerBuffer;
_player.onProgress = handlePlayerProgress;
_player.onStatusChange = handlePlayerStatusChange;
}
);
@@ -60,14 +124,6 @@ const VideoDemo = () => {
// Progress state
const [progress, setProgress] = React.useState(0);
React.useEffect(() => {
const interval = setInterval(() => {
setProgress(
show ? (isNaN(player.currentTime) ? 0 : player.currentTime) : 0
);
}, 300);
return () => clearInterval(interval);
}, [player, show]);
// Handlers
const handleSeek = (val: number) => {
@@ -89,6 +145,8 @@ const VideoDemo = () => {
controls={showNativeControls}
pictureInPicture={true}
autoEnterPictureInPicture={true}
onFullscreenChange={handleFullscreenChange}
onPictureInPictureChange={handlePictureInPictureChange}
/>
) : (
<View style={styles.hiddenVideo}>
@@ -117,6 +175,13 @@ const VideoDemo = () => {
</Text>
</View>
{/* Event log */}
<View style={{ marginBottom: 8 }}>
<Text style={{ color: '#888', fontSize: 12 }}>
Last event: {lastEvent}
</Text>
</View>
{/* Controls */}
<View style={styles.controlsRow}>
<IconButton icon="⏮" onPress={() => player.seekTo(0)} />