2015-12-06 22:25:18 -08:00
|
|
|
'use strict';
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
import React, {FC, useRef, useState} from 'react';
|
2016-04-22 00:01:44 -04:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
import {TouchableOpacity, View} from 'react-native';
|
2016-02-10 11:39:54 +00:00
|
|
|
|
2023-10-26 08:46:04 +02:00
|
|
|
import Video, {
|
|
|
|
AudioTrack,
|
|
|
|
OnAudioTracksData,
|
|
|
|
OnLoadData,
|
|
|
|
OnProgressData,
|
|
|
|
OnTextTracksData,
|
|
|
|
OnVideoAspectRatioData,
|
|
|
|
TextTrack,
|
|
|
|
OnBufferData,
|
|
|
|
OnAudioFocusChangedData,
|
|
|
|
OnVideoErrorData,
|
|
|
|
VideoRef,
|
2024-02-29 22:41:04 +09:00
|
|
|
OnTextTrackDataChangedData,
|
2024-04-05 10:35:57 +02:00
|
|
|
OnSeekData,
|
2024-04-04 14:45:39 +02:00
|
|
|
OnPlaybackStateChangedData,
|
|
|
|
OnPlaybackRateChangeData,
|
2024-05-22 14:01:55 +02:00
|
|
|
OnVideoTracksData,
|
|
|
|
SelectedVideoTrackType,
|
2024-05-11 22:02:04 +02:00
|
|
|
BufferingStrategyType,
|
2024-05-22 14:01:55 +02:00
|
|
|
ReactVideoSource,
|
2024-06-28 13:03:10 +03:30
|
|
|
SelectedTrackType,
|
2023-10-26 08:46:04 +02:00
|
|
|
} from 'react-native-video';
|
2024-05-22 14:01:55 +02:00
|
|
|
import styles from './styles';
|
2024-06-28 13:03:10 +03:30
|
|
|
import {AdditionalSourceInfo} from './types';
|
|
|
|
import {
|
|
|
|
bufferConfig,
|
|
|
|
defaultValue,
|
|
|
|
srcList,
|
|
|
|
textTracksSelectionBy,
|
|
|
|
} from './constants';
|
|
|
|
import {Overlay, toast} from './components';
|
|
|
|
|
|
|
|
type Props = NonNullable<unknown>;
|
|
|
|
|
|
|
|
const VideoPlayer: FC<Props> = ({}) => {
|
|
|
|
const [state, setState] = useState(defaultValue);
|
|
|
|
const videoRef = useRef<VideoRef>(null);
|
|
|
|
const viewStyle = state.fullscreen ? styles.fullScreen : styles.halfScreen;
|
|
|
|
const currentSrc = srcList[state.srcListId];
|
|
|
|
const additional = currentSrc as AdditionalSourceInfo;
|
|
|
|
|
|
|
|
const onAudioTracks = (data: OnAudioTracksData) => {
|
2023-10-26 08:46:04 +02:00
|
|
|
const selectedTrack = data.audioTracks?.find((x: AudioTrack) => {
|
2023-10-07 23:14:09 +02:00
|
|
|
return x.selected;
|
|
|
|
});
|
2024-05-22 14:01:55 +02:00
|
|
|
if (selectedTrack?.index) {
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2024-03-22 07:58:09 +01:00
|
|
|
audioTracks: data.audioTracks,
|
2022-04-26 22:59:04 +02:00
|
|
|
selectedAudioTrack: {
|
2024-06-28 13:03:10 +03:30
|
|
|
type: SelectedTrackType.INDEX,
|
2024-05-22 14:01:55 +02:00
|
|
|
value: selectedTrack?.index,
|
2022-04-26 22:59:04 +02:00
|
|
|
},
|
2023-10-07 23:14:09 +02:00
|
|
|
});
|
2024-03-22 07:58:09 +01:00
|
|
|
} else {
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2024-03-22 07:58:09 +01:00
|
|
|
audioTracks: data.audioTracks,
|
|
|
|
});
|
2022-04-26 22:59:04 +02:00
|
|
|
}
|
2023-10-07 23:14:09 +02:00
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onVideoTracks = (data: OnVideoTracksData) => {
|
2024-05-22 14:01:55 +02:00
|
|
|
console.log('onVideoTracks', data.videoTracks);
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2024-05-22 14:01:55 +02:00
|
|
|
videoTracks: data.videoTracks,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onTextTracks = (data: OnTextTracksData) => {
|
2023-10-26 08:46:04 +02:00
|
|
|
const selectedTrack = data.textTracks?.find((x: TextTrack) => {
|
2024-02-29 22:41:04 +09:00
|
|
|
return x?.selected;
|
2023-10-07 23:14:09 +02:00
|
|
|
});
|
2022-04-26 22:59:04 +02:00
|
|
|
|
|
|
|
if (selectedTrack?.language) {
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2024-03-22 07:58:09 +01:00
|
|
|
textTracks: data.textTracks,
|
2024-05-22 14:01:55 +02:00
|
|
|
selectedTextTrack:
|
2024-06-28 13:03:10 +03:30
|
|
|
textTracksSelectionBy === 'index'
|
2024-05-22 14:01:55 +02:00
|
|
|
? {
|
2024-06-28 13:03:10 +03:30
|
|
|
type: SelectedTrackType.INDEX,
|
2024-05-22 14:01:55 +02:00
|
|
|
value: selectedTrack?.index,
|
|
|
|
}
|
|
|
|
: {
|
2024-06-28 13:03:10 +03:30
|
|
|
type: SelectedTrackType.LANGUAGE,
|
2024-05-22 14:01:55 +02:00
|
|
|
value: selectedTrack?.language,
|
|
|
|
},
|
2023-10-07 23:14:09 +02:00
|
|
|
});
|
2024-03-22 07:58:09 +01:00
|
|
|
} else {
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2024-03-22 07:58:09 +01:00
|
|
|
textTracks: data.textTracks,
|
|
|
|
});
|
2022-04-26 22:59:04 +02:00
|
|
|
}
|
2023-10-07 23:14:09 +02:00
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onLoad = (data: OnLoadData) => {
|
|
|
|
onAudioTracks(data);
|
|
|
|
onTextTracks(data);
|
|
|
|
onVideoTracks(data);
|
|
|
|
setState({...state, duration: data.duration});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onProgress = (data: OnProgressData) => {
|
|
|
|
setState({...state, currentTime: data.currentTime});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onSeek = (data: OnSeekData) => {
|
|
|
|
setState({...state, currentTime: data.currentTime, isSeeking: false});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onVideoLoadStart = () => {
|
|
|
|
console.log('onVideoLoadStart');
|
|
|
|
setState({...state, isLoading: true});
|
|
|
|
};
|
|
|
|
|
|
|
|
const onTextTrackDataChanged = (data: OnTextTrackDataChangedData) => {
|
2024-02-29 22:41:04 +09:00
|
|
|
console.log(`Subtitles: ${JSON.stringify(data, null, 2)}`);
|
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onAspectRatio = (data: OnVideoAspectRatioData) => {
|
2023-10-07 23:14:09 +02:00
|
|
|
console.log('onAspectRadio called ' + JSON.stringify(data));
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({
|
|
|
|
...state,
|
2022-04-26 22:59:04 +02:00
|
|
|
videoWidth: data.width,
|
|
|
|
videoHeight: data.height,
|
2023-10-07 23:14:09 +02:00
|
|
|
});
|
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onVideoBuffer = (param: OnBufferData) => {
|
2023-10-07 23:14:09 +02:00
|
|
|
console.log('onVideoBuffer');
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({...state, isLoading: param.isBuffering});
|
2023-10-07 23:14:09 +02:00
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onReadyForDisplay = () => {
|
2023-10-07 23:14:09 +02:00
|
|
|
console.log('onReadyForDisplay');
|
2024-06-28 13:03:10 +03:30
|
|
|
setState({...state, isLoading: false});
|
2017-01-11 12:51:45 +00:00
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onAudioBecomingNoisy = () => {
|
|
|
|
setState({...state, paused: true});
|
2017-01-11 12:51:45 +00:00
|
|
|
};
|
2015-12-06 22:25:18 -08:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onAudioFocusChanged = (event: OnAudioFocusChangedData) => {
|
|
|
|
setState({...state, paused: !event.hasAudioFocus});
|
2023-10-07 23:14:09 +02:00
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onError = (err: OnVideoErrorData) => {
|
2023-10-26 08:46:04 +02:00
|
|
|
console.log(JSON.stringify(err));
|
2024-06-28 13:03:10 +03:30
|
|
|
toast(true, 'error: ' + JSON.stringify(err));
|
2023-10-07 23:14:09 +02:00
|
|
|
};
|
2022-04-26 22:59:04 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onEnd = () => {
|
|
|
|
if (!state.loop) {
|
|
|
|
channelUp();
|
2024-04-26 09:42:21 +02:00
|
|
|
}
|
2022-04-26 22:59:04 +02:00
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onPlaybackRateChange = (data: OnPlaybackRateChangeData) => {
|
2024-04-04 14:45:39 +02:00
|
|
|
console.log('onPlaybackRateChange', data);
|
2024-04-19 22:38:52 +02:00
|
|
|
};
|
2024-04-04 14:45:39 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const onPlaybackStateChanged = (data: OnPlaybackStateChangedData) => {
|
2024-04-04 14:45:39 +02:00
|
|
|
console.log('onPlaybackStateChanged', data);
|
2024-04-19 22:38:52 +02:00
|
|
|
};
|
2024-04-04 14:45:39 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const goToChannel = (channel: number) => {
|
|
|
|
setState({
|
|
|
|
...state,
|
2022-04-26 22:59:04 +02:00
|
|
|
srcListId: channel,
|
|
|
|
duration: 0.0,
|
|
|
|
currentTime: 0.0,
|
|
|
|
videoWidth: 0,
|
|
|
|
videoHeight: 0,
|
|
|
|
isLoading: false,
|
|
|
|
audioTracks: [],
|
|
|
|
textTracks: [],
|
|
|
|
selectedAudioTrack: undefined,
|
|
|
|
selectedTextTrack: undefined,
|
2024-05-22 14:01:55 +02:00
|
|
|
selectedVideoTrack: {
|
|
|
|
type: SelectedVideoTrackType.AUTO,
|
|
|
|
},
|
2023-10-07 23:14:09 +02:00
|
|
|
});
|
2023-11-22 15:03:57 +01:00
|
|
|
};
|
2022-09-11 17:01:53 +02:00
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const channelUp = () => {
|
|
|
|
console.log('channel up');
|
|
|
|
goToChannel((state.srcListId + 1) % srcList.length);
|
2024-05-22 14:01:55 +02:00
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
const channelDown = () => {
|
|
|
|
console.log('channel down');
|
|
|
|
goToChannel((state.srcListId + srcList.length - 1) % srcList.length);
|
2024-05-22 14:01:55 +02:00
|
|
|
};
|
|
|
|
|
2024-06-28 13:03:10 +03:30
|
|
|
return (
|
|
|
|
<View style={styles.container}>
|
|
|
|
{(srcList[state.srcListId] as AdditionalSourceInfo)?.noView ? null : (
|
|
|
|
<TouchableOpacity style={viewStyle}>
|
|
|
|
<Video
|
|
|
|
showNotificationControls={state.showNotificationControls}
|
|
|
|
ref={videoRef}
|
|
|
|
source={currentSrc as ReactVideoSource}
|
|
|
|
textTracks={additional?.textTracks}
|
|
|
|
adTagUrl={additional?.adTagUrl}
|
|
|
|
drm={additional?.drm}
|
|
|
|
style={viewStyle}
|
|
|
|
rate={state.rate}
|
|
|
|
paused={state.paused}
|
|
|
|
volume={state.volume}
|
|
|
|
muted={state.muted}
|
|
|
|
fullscreen={state.fullscreen}
|
|
|
|
controls={state.showRNVControls}
|
|
|
|
resizeMode={state.resizeMode}
|
|
|
|
onLoad={onLoad}
|
|
|
|
onAudioTracks={onAudioTracks}
|
|
|
|
onTextTracks={onTextTracks}
|
|
|
|
onVideoTracks={onVideoTracks}
|
|
|
|
onTextTrackDataChanged={onTextTrackDataChanged}
|
|
|
|
onProgress={onProgress}
|
|
|
|
onEnd={onEnd}
|
|
|
|
progressUpdateInterval={1000}
|
|
|
|
onError={onError}
|
|
|
|
onAudioBecomingNoisy={onAudioBecomingNoisy}
|
|
|
|
onAudioFocusChanged={onAudioFocusChanged}
|
|
|
|
onLoadStart={onVideoLoadStart}
|
|
|
|
onAspectRatio={onAspectRatio}
|
|
|
|
onReadyForDisplay={onReadyForDisplay}
|
|
|
|
onBuffer={onVideoBuffer}
|
|
|
|
onSeek={onSeek}
|
|
|
|
repeat={state.loop}
|
|
|
|
selectedTextTrack={state.selectedTextTrack}
|
|
|
|
selectedAudioTrack={state.selectedAudioTrack}
|
|
|
|
selectedVideoTrack={state.selectedVideoTrack}
|
|
|
|
playInBackground={false}
|
|
|
|
bufferConfig={{
|
|
|
|
...bufferConfig,
|
|
|
|
cacheSizeMB: state.useCache ? 200 : 0,
|
|
|
|
}}
|
|
|
|
preventsDisplaySleepDuringVideoPlayback={true}
|
|
|
|
poster={state.poster}
|
|
|
|
onPlaybackRateChange={onPlaybackRateChange}
|
|
|
|
onPlaybackStateChanged={onPlaybackStateChanged}
|
|
|
|
bufferingStrategy={BufferingStrategyType.DEFAULT}
|
|
|
|
debug={{enable: true, thread: true}}
|
|
|
|
/>
|
|
|
|
</TouchableOpacity>
|
|
|
|
)}
|
|
|
|
<Overlay
|
|
|
|
channelDown={channelDown}
|
|
|
|
channelUp={channelUp}
|
|
|
|
setState={setState}
|
|
|
|
state={state}
|
|
|
|
ref={videoRef}
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
};
|
2023-10-07 23:14:09 +02:00
|
|
|
export default VideoPlayer;
|