Merge remote-tracking branch 'origin/master' into feat/web
This commit is contained in:
@@ -83,8 +83,6 @@ android {
|
||||
namespace "com.videoplayer"
|
||||
|
||||
compileOptions {
|
||||
// These options are necessary to be able to build fro source
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
@@ -155,8 +153,6 @@ dependencies {
|
||||
because("kotlin-stdlib-jdk8 is now a part of kotlin-stdlib")
|
||||
}
|
||||
}
|
||||
// coreLibraryDesugaring is mandatory to be able to build exoplayer from source
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
|
||||
}
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -16,14 +16,15 @@
|
||||
"dependencies": {
|
||||
"@expo/metro-runtime": "~3.2.1",
|
||||
"@react-native-picker/picker": "2.7.5",
|
||||
"expo": "^51.0.17",
|
||||
"expo-asset": "^10.0.9",
|
||||
"expo-image": "^1.12.12",
|
||||
"expo": "^51.0.32",
|
||||
"expo-asset": "~10.0.10",
|
||||
"expo-image": "^1.12.15",
|
||||
"expo-navigation-bar": "~3.0.7",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.74.3",
|
||||
"react-native": "0.74.5",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native-web": "~0.19.10",
|
||||
"react-native-windows": "0.74.1"
|
||||
"react-native-windows": "0.74.19"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.0",
|
||||
|
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
import React, {type FC, useCallback, useRef, useState} from 'react';
|
||||
import React, {type FC, useCallback, useRef, useState, useEffect} from 'react';
|
||||
|
||||
import {Platform, TouchableOpacity, View} from 'react-native';
|
||||
import {Platform, TouchableOpacity, View, StatusBar} from 'react-native';
|
||||
|
||||
import Video, {
|
||||
VideoRef,
|
||||
@@ -26,23 +26,24 @@ import Video, {
|
||||
type OnPlaybackRateChangeData,
|
||||
type OnVideoTracksData,
|
||||
type ReactVideoSource,
|
||||
type TextTracks,
|
||||
type VideoTrack,
|
||||
type SelectedTrack,
|
||||
type SelectedVideoTrack,
|
||||
type EnumValues,
|
||||
OnBandwidthUpdateData,
|
||||
ControlsStyles,
|
||||
} from 'react-native-video';
|
||||
import styles from './styles';
|
||||
import {type AdditionalSourceInfo} from './types';
|
||||
import {bufferConfig, srcList, textTracksSelectionBy} from './constants';
|
||||
import {Overlay, toast} from './components';
|
||||
|
||||
type AdditionnalSourceInfo = {
|
||||
textTracks: TextTracks;
|
||||
adTagUrl: string;
|
||||
description: string;
|
||||
noView: boolean;
|
||||
};
|
||||
import {
|
||||
bufferConfig,
|
||||
isAndroid,
|
||||
srcList,
|
||||
textTracksSelectionBy,
|
||||
audioTracksSelectionBy,
|
||||
} from './constants';
|
||||
import {Overlay, toast, VideoLoader} from './components';
|
||||
import * as NavigationBar from 'expo-navigation-bar';
|
||||
|
||||
type Props = NonNullable<unknown>;
|
||||
|
||||
@@ -76,7 +77,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
const [repeat, setRepeat] = useState(false);
|
||||
const [controls, setControls] = useState(false);
|
||||
const [useCache, setUseCache] = useState(false);
|
||||
const [poster, setPoster] = useState<string | undefined>(undefined);
|
||||
const [showPoster, setShowPoster] = useState<boolean>(false);
|
||||
const [showNotificationControls, setShowNotificationControls] =
|
||||
useState(false);
|
||||
const [isSeeking, setIsSeeking] = useState(false);
|
||||
@@ -111,19 +112,30 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
goToChannel((srcListId + srcList.length - 1) % srcList.length);
|
||||
}, [goToChannel, srcListId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isAndroid) {
|
||||
NavigationBar.setVisibilityAsync('visible');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onAudioTracks = (data: OnAudioTracksData) => {
|
||||
console.log('onAudioTracks', data);
|
||||
const selectedTrack = data.audioTracks?.find((x: AudioTrack) => {
|
||||
return x.selected;
|
||||
});
|
||||
if (selectedTrack?.index) {
|
||||
setAudioTracks(data.audioTracks);
|
||||
setSelectedAudioTrack({
|
||||
type: SelectedTrackType.INDEX,
|
||||
value: selectedTrack.index,
|
||||
});
|
||||
} else {
|
||||
setAudioTracks(data.audioTracks);
|
||||
let value;
|
||||
if (audioTracksSelectionBy === SelectedTrackType.INDEX) {
|
||||
value = selectedTrack?.index;
|
||||
} else if (audioTracksSelectionBy === SelectedTrackType.LANGUAGE) {
|
||||
value = selectedTrack?.language;
|
||||
} else if (audioTracksSelectionBy === SelectedTrackType.TITLE) {
|
||||
value = selectedTrack?.title;
|
||||
}
|
||||
setAudioTracks(data.audioTracks);
|
||||
setSelectedAudioTrack({
|
||||
type: audioTracksSelectionBy,
|
||||
value: value,
|
||||
});
|
||||
};
|
||||
|
||||
const onVideoTracks = (data: OnVideoTracksData) => {
|
||||
@@ -136,22 +148,19 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
return x?.selected;
|
||||
});
|
||||
|
||||
if (selectedTrack?.language) {
|
||||
setTextTracks(data.textTracks);
|
||||
if (textTracksSelectionBy === 'index') {
|
||||
setSelectedTextTrack({
|
||||
type: SelectedTrackType.INDEX,
|
||||
value: selectedTrack?.index,
|
||||
});
|
||||
} else {
|
||||
setSelectedTextTrack({
|
||||
type: SelectedTrackType.LANGUAGE,
|
||||
value: selectedTrack?.language,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
setTextTracks(data.textTracks);
|
||||
setTextTracks(data.textTracks);
|
||||
let value;
|
||||
if (textTracksSelectionBy === SelectedTrackType.INDEX) {
|
||||
value = selectedTrack?.index;
|
||||
} else if (textTracksSelectionBy === SelectedTrackType.LANGUAGE) {
|
||||
value = selectedTrack?.language;
|
||||
} else if (textTracksSelectionBy === SelectedTrackType.TITLE) {
|
||||
value = selectedTrack?.title;
|
||||
}
|
||||
setSelectedTextTrack({
|
||||
type: textTracksSelectionBy,
|
||||
value: value,
|
||||
});
|
||||
};
|
||||
|
||||
const onLoad = (data: OnLoadData) => {
|
||||
@@ -221,28 +230,48 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
console.log('onPlaybackStateChanged', data);
|
||||
};
|
||||
|
||||
const onVideoBandwidthUpdate = (data: OnBandwidthUpdateData) => {
|
||||
console.log('onVideoBandwidthUpdate', data);
|
||||
};
|
||||
|
||||
const onFullScreenExit = () => {
|
||||
// iOS pauses video on exit from full screen
|
||||
Platform.OS === 'ios' && setPaused(true);
|
||||
};
|
||||
|
||||
const _renderLoader = showPoster ? () => <VideoLoader /> : undefined;
|
||||
|
||||
const _subtitleStyle = {subtitlesFollowVideo: true};
|
||||
const _controlsStyles : ControlsStyles = {
|
||||
hideNavigationBarOnFullScreenMode: true,
|
||||
hideNotificationBarOnFullScreenMode: true,
|
||||
liveLabel: "LIVE"
|
||||
};
|
||||
const _bufferConfig = {
|
||||
...bufferConfig,
|
||||
cacheSizeMB: useCache ? 200 : 0,
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
videoRef.current?.setSource(currentSrc)
|
||||
}, [currentSrc])
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<StatusBar animated={true} backgroundColor="black" hidden={false} />
|
||||
|
||||
{(srcList[srcListId] as AdditionalSourceInfo)?.noView ? null : (
|
||||
<TouchableOpacity style={viewStyle}>
|
||||
<Video
|
||||
showNotificationControls={showNotificationControls}
|
||||
ref={videoRef}
|
||||
source={currentSrc as ReactVideoSource}
|
||||
textTracks={additional?.textTracks}
|
||||
adTagUrl={additional?.adTagUrl}
|
||||
// source={currentSrc as ReactVideoSource}
|
||||
drm={additional?.drm}
|
||||
style={viewStyle}
|
||||
rate={rate}
|
||||
paused={paused}
|
||||
volume={volume}
|
||||
muted={muted}
|
||||
fullscreen={fullscreen}
|
||||
controls={controls}
|
||||
resizeMode={resizeMode}
|
||||
onFullscreenPlayerWillDismiss={onFullScreenExit}
|
||||
@@ -261,22 +290,22 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
onAspectRatio={onAspectRatio}
|
||||
onReadyForDisplay={onReadyForDisplay}
|
||||
onBuffer={onVideoBuffer}
|
||||
onBandwidthUpdate={onVideoBandwidthUpdate}
|
||||
onSeek={onSeek}
|
||||
repeat={repeat}
|
||||
selectedTextTrack={selectedTextTrack}
|
||||
selectedAudioTrack={selectedAudioTrack}
|
||||
selectedVideoTrack={selectedVideoTrack}
|
||||
playInBackground={false}
|
||||
bufferConfig={{
|
||||
...bufferConfig,
|
||||
cacheSizeMB: useCache ? 200 : 0,
|
||||
}}
|
||||
bufferConfig={_bufferConfig}
|
||||
preventsDisplaySleepDuringVideoPlayback={true}
|
||||
poster={poster}
|
||||
renderLoader={_renderLoader}
|
||||
onPlaybackRateChange={onPlaybackRateChange}
|
||||
onPlaybackStateChanged={onPlaybackStateChanged}
|
||||
bufferingStrategy={BufferingStrategyType.DEFAULT}
|
||||
debug={{enable: true, thread: true}}
|
||||
subtitleStyle={_subtitleStyle}
|
||||
controlsStyles={_controlsStyles}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)}
|
||||
@@ -302,7 +331,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
paused={paused}
|
||||
volume={volume}
|
||||
setControls={setControls}
|
||||
poster={poster}
|
||||
showPoster={showPoster}
|
||||
rate={rate}
|
||||
setFullscreen={setFullscreen}
|
||||
setPaused={setPaused}
|
||||
@@ -311,7 +340,7 @@ const VideoPlayer: FC<Props> = ({}) => {
|
||||
setIsSeeking={setIsSeeking}
|
||||
repeat={repeat}
|
||||
setRepeat={setRepeat}
|
||||
setPoster={setPoster}
|
||||
setShowPoster={setShowPoster}
|
||||
setRate={setRate}
|
||||
setResizeMode={setResizeMode}
|
||||
setShowNotificationControls={setShowNotificationControls}
|
||||
|
@@ -1,19 +1,25 @@
|
||||
import {Picker} from '@react-native-picker/picker';
|
||||
import {Text} from 'react-native';
|
||||
import type {AudioTrack, SelectedTrack} from 'react-native-video';
|
||||
import {
|
||||
SelectedTrackType,
|
||||
type AudioTrack,
|
||||
type SelectedTrack,
|
||||
} from 'react-native-video';
|
||||
import styles from '../styles';
|
||||
import React from 'react';
|
||||
|
||||
export interface AudioTrackSelectorType {
|
||||
audioTracks: Array<AudioTrack>;
|
||||
selectedAudioTrack: SelectedTrack | undefined;
|
||||
onValueChange: (arg0: string) => void;
|
||||
onValueChange: (arg0: string | number) => void;
|
||||
audioTracksSelectionBy: SelectedTrackType;
|
||||
}
|
||||
|
||||
export const AudioTrackSelector = ({
|
||||
audioTracks,
|
||||
selectedAudioTrack,
|
||||
onValueChange,
|
||||
audioTracksSelectionBy,
|
||||
}: AudioTrackSelectorType) => {
|
||||
return (
|
||||
<>
|
||||
@@ -25,7 +31,7 @@ export const AudioTrackSelector = ({
|
||||
onValueChange={itemValue => {
|
||||
if (itemValue !== 'empty') {
|
||||
console.log('on audio value change ' + itemValue);
|
||||
onValueChange(`${itemValue}`);
|
||||
onValueChange(itemValue);
|
||||
}
|
||||
}}>
|
||||
{audioTracks?.length <= 0 ? (
|
||||
@@ -37,11 +43,19 @@ export const AudioTrackSelector = ({
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
let value;
|
||||
if (audioTracksSelectionBy === SelectedTrackType.INDEX) {
|
||||
value = track.index;
|
||||
} else if (audioTracksSelectionBy === SelectedTrackType.LANGUAGE) {
|
||||
value = track.language;
|
||||
} else if (audioTracksSelectionBy === SelectedTrackType.TITLE) {
|
||||
value = track.title;
|
||||
}
|
||||
return (
|
||||
<Picker.Item
|
||||
label={`${track.language} - ${track.title} - ${track.selected}`}
|
||||
value={`${track.index}`}
|
||||
key={`${track.index}`}
|
||||
label={`${value} - ${track.selected}`}
|
||||
value={`${value}`}
|
||||
key={`${value}`}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@@ -1,22 +1,8 @@
|
||||
import React, {FC, memo} from 'react';
|
||||
import {ActivityIndicator, View} from 'react-native';
|
||||
import styles from '../styles.tsx';
|
||||
import React, {memo} from 'react';
|
||||
import {ActivityIndicator} from 'react-native';
|
||||
|
||||
type Props = {
|
||||
isLoading: boolean;
|
||||
};
|
||||
|
||||
const _Indicator: FC<Props> = ({isLoading}) => {
|
||||
if (!isLoading) {
|
||||
return <View />;
|
||||
}
|
||||
return (
|
||||
<ActivityIndicator
|
||||
color="#3235fd"
|
||||
size="large"
|
||||
style={styles.IndicatorStyle}
|
||||
/>
|
||||
);
|
||||
const _Indicator = () => {
|
||||
return <ActivityIndicator color="#3235fd" size="large" />;
|
||||
};
|
||||
|
||||
export const Indicator = memo(_Indicator);
|
||||
|
@@ -21,7 +21,7 @@ interface MultiValueControlType<T> {
|
||||
onPress: (arg: T) => void;
|
||||
}
|
||||
|
||||
const MultiValueControl = <T extends number | string | ResizeMode>({
|
||||
export const MultiValueControl = <T extends number | string | ResizeMode>({
|
||||
values,
|
||||
selected,
|
||||
onPress,
|
@@ -5,19 +5,14 @@ import React, {
|
||||
type Dispatch,
|
||||
type SetStateAction,
|
||||
} from 'react';
|
||||
import {Indicator} from './Indicator.tsx';
|
||||
import {View} from 'react-native';
|
||||
import styles from '../styles.tsx';
|
||||
import ToggleControl from '../ToggleControl.tsx';
|
||||
import {
|
||||
isAndroid,
|
||||
isIos,
|
||||
samplePoster,
|
||||
textTracksSelectionBy,
|
||||
audioTracksSelectionBy,
|
||||
} from '../constants';
|
||||
import MultiValueControl, {
|
||||
type MultiValueControlPropType,
|
||||
} from '../MultiValueControl.tsx';
|
||||
import {
|
||||
ResizeMode,
|
||||
VideoRef,
|
||||
@@ -31,14 +26,15 @@ import {
|
||||
type VideoTrack,
|
||||
type AudioTrack,
|
||||
} from 'react-native-video';
|
||||
import {
|
||||
toast,
|
||||
Seeker,
|
||||
AudioTrackSelector,
|
||||
TextTrackSelector,
|
||||
VideoTrackSelector,
|
||||
TopControl,
|
||||
} from '../components';
|
||||
|
||||
import {toast} from './Toast';
|
||||
import {Seeker} from './Seeker';
|
||||
import {AudioTrackSelector} from './AudioTracksSelector';
|
||||
import {VideoTrackSelector} from './VideoTracksSelector';
|
||||
import {TextTrackSelector} from './TextTracksSelector';
|
||||
import {TopControl} from './TopControl';
|
||||
import {ToggleControl} from './ToggleControl';
|
||||
import {MultiValueControl} from './MultiValueControl';
|
||||
|
||||
type Props = {
|
||||
channelDown: () => void;
|
||||
@@ -69,8 +65,8 @@ type Props = {
|
||||
setPaused: Dispatch<SetStateAction<boolean>>;
|
||||
repeat: boolean;
|
||||
setRepeat: Dispatch<SetStateAction<boolean>>;
|
||||
poster: string | undefined;
|
||||
setPoster: Dispatch<SetStateAction<string | undefined>>;
|
||||
showPoster: boolean;
|
||||
setShowPoster: Dispatch<SetStateAction<boolean>>;
|
||||
muted: boolean;
|
||||
setMuted: Dispatch<SetStateAction<boolean>>;
|
||||
currentTime: number;
|
||||
@@ -108,8 +104,8 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
setPaused,
|
||||
setRepeat,
|
||||
repeat,
|
||||
setPoster,
|
||||
poster,
|
||||
setShowPoster,
|
||||
showPoster,
|
||||
setMuted,
|
||||
muted,
|
||||
duration,
|
||||
@@ -157,27 +153,20 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
setShowNotificationControls(prev => !prev);
|
||||
};
|
||||
|
||||
const onSelectedAudioTrackChange = (itemValue: string) => {
|
||||
const onSelectedAudioTrackChange = (itemValue: string | number) => {
|
||||
console.log('on audio value change ' + itemValue);
|
||||
if (itemValue === 'none') {
|
||||
setSelectedAudioTrack({
|
||||
type: SelectedTrackType.DISABLED,
|
||||
});
|
||||
} else {
|
||||
setSelectedAudioTrack({
|
||||
type: SelectedTrackType.INDEX,
|
||||
value: itemValue,
|
||||
});
|
||||
setSelectedAudioTrack({type: audioTracksSelectionBy, value: itemValue});
|
||||
}
|
||||
};
|
||||
|
||||
const onSelectedTextTrackChange = (itemValue: string) => {
|
||||
console.log('on value change ' + itemValue);
|
||||
const type =
|
||||
textTracksSelectionBy === 'index'
|
||||
? SelectedTrackType.INDEX
|
||||
: SelectedTrackType.LANGUAGE;
|
||||
setSelectedTextTrack({type, value: itemValue});
|
||||
setSelectedTextTrack({type: textTracksSelectionBy, value: itemValue});
|
||||
};
|
||||
|
||||
const onSelectedVideoTrackChange = (itemValue: string) => {
|
||||
@@ -217,14 +206,12 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
|
||||
const toggleRepeat = () => setRepeat(prev => !prev);
|
||||
|
||||
const togglePoster = () =>
|
||||
setPoster(prev => (prev ? undefined : samplePoster));
|
||||
const togglePoster = () => setShowPoster(prev => !prev);
|
||||
|
||||
const toggleMuted = () => setMuted(prev => !prev);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Indicator isLoading={isLoading} />
|
||||
<View style={styles.topControls}>
|
||||
<View style={styles.resizeModeControl}>
|
||||
<TopControl
|
||||
@@ -270,7 +257,7 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
<ToggleControl onPress={toggleFullscreen} text="fullscreen" />
|
||||
<ToggleControl onPress={openDecoration} text="decoration" />
|
||||
<ToggleControl
|
||||
isSelected={!!poster}
|
||||
isSelected={showPoster}
|
||||
onPress={togglePoster}
|
||||
selectedText="poster"
|
||||
unselectedText="no poster"
|
||||
@@ -339,6 +326,7 @@ const _Overlay = forwardRef<VideoRef, Props>((props, ref) => {
|
||||
audioTracks={audioTracks}
|
||||
selectedAudioTrack={selectedAudioTrack}
|
||||
onValueChange={onSelectedAudioTrackChange}
|
||||
audioTracksSelectionBy={audioTracksSelectionBy}
|
||||
/>
|
||||
<TextTrackSelector
|
||||
textTracks={textTracks}
|
||||
|
@@ -1,6 +1,10 @@
|
||||
import {Picker} from '@react-native-picker/picker';
|
||||
import {Text} from 'react-native';
|
||||
import type {TextTrack, SelectedTrack} from 'react-native-video';
|
||||
import {
|
||||
type TextTrack,
|
||||
type SelectedTrack,
|
||||
SelectedTrackType,
|
||||
} from 'react-native-video';
|
||||
import styles from '../styles';
|
||||
import React from 'react';
|
||||
|
||||
@@ -38,23 +42,15 @@ export const TextTrackSelector = ({
|
||||
if (!track) {
|
||||
return;
|
||||
}
|
||||
if (textTracksSelectionBy === 'index') {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={`${track.index}`}
|
||||
value={track.index}
|
||||
key={track.index}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Picker.Item
|
||||
label={track.language}
|
||||
value={track.language}
|
||||
key={track.language}
|
||||
/>
|
||||
);
|
||||
let value;
|
||||
if (textTracksSelectionBy === SelectedTrackType.INDEX) {
|
||||
value = track.index;
|
||||
} else if (textTracksSelectionBy === SelectedTrackType.LANGUAGE) {
|
||||
value = track.language;
|
||||
} else if (textTracksSelectionBy === SelectedTrackType.TITLE) {
|
||||
value = track.title;
|
||||
}
|
||||
return <Picker.Item label={`${value}`} value={value} key={value} />;
|
||||
})}
|
||||
</Picker>
|
||||
</>
|
||||
|
@@ -25,7 +25,7 @@ interface ToggleControlType {
|
||||
onPress: () => void;
|
||||
}
|
||||
|
||||
const ToggleControl = ({
|
||||
export const ToggleControl = ({
|
||||
isSelected,
|
||||
selectedText,
|
||||
unselectedText,
|
15
examples/basic/src/components/VideoLoader.tsx
Normal file
15
examples/basic/src/components/VideoLoader.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import {Text, View} from 'react-native';
|
||||
import {Indicator} from './Indicator.tsx';
|
||||
import React, {memo} from 'react';
|
||||
import styles from '../styles.tsx';
|
||||
|
||||
const _VideoLoader = () => {
|
||||
return (
|
||||
<View style={styles.indicatorContainer}>
|
||||
<Text style={styles.indicatorText}>Loading...</Text>
|
||||
<Indicator />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export const VideoLoader = memo(_VideoLoader);
|
@@ -1,3 +1,4 @@
|
||||
export * from './VideoLoader';
|
||||
export * from './Indicator';
|
||||
export * from './Seeker';
|
||||
export * from './AudioTracksSelector';
|
||||
@@ -6,3 +7,5 @@ export * from './TextTracksSelector';
|
||||
export * from './Overlay';
|
||||
export * from './TopControl';
|
||||
export * from './Toast';
|
||||
export * from './ToggleControl';
|
||||
export * from './MultiValueControl';
|
||||
|
@@ -2,13 +2,19 @@ import {
|
||||
BufferConfig,
|
||||
DRMType,
|
||||
ISO639_1,
|
||||
SelectedTrackType,
|
||||
TextTrackType,
|
||||
} from 'react-native-video';
|
||||
import {SampleVideoSource} from '../types';
|
||||
import {localeVideo} from '../assets';
|
||||
import {Platform} from 'react-native';
|
||||
|
||||
export const textTracksSelectionBy = 'index';
|
||||
// This constant allows to change how the sample behaves regarding to audio and texts selection.
|
||||
// You can change it to change how selector will use tracks information.
|
||||
// by default, index will be displayed and index will be applied to selected tracks.
|
||||
// You can also use LANGUAGE or TITLE
|
||||
export const textTracksSelectionBy = SelectedTrackType.INDEX;
|
||||
export const audioTracksSelectionBy = SelectedTrackType.INDEX;
|
||||
|
||||
export const isIos = Platform.OS === 'ios';
|
||||
|
||||
@@ -25,6 +31,10 @@ export const srcAllPlatformList = [
|
||||
cropStart: 3000,
|
||||
cropEnd: 10000,
|
||||
},
|
||||
{
|
||||
description: 'video with 90° rotation',
|
||||
uri: 'https://bn-dev.fra1.digitaloceanspaces.com/km-tournament/uploads/rn_image_picker_lib_temp_2ee86a27_9312_4548_84af_7fd75d9ad4dd_ad8b20587a.mp4',
|
||||
},
|
||||
{
|
||||
description: 'local file portrait',
|
||||
uri: localeVideo.portrait,
|
||||
@@ -86,6 +96,11 @@ export const srcAllPlatformList = [
|
||||
uri: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8',
|
||||
startPosition: 50000,
|
||||
},
|
||||
{
|
||||
description: 'mp3 with texttrack',
|
||||
uri: 'https://traffic.libsyn.com/democracynow/wx2024-0702_SOT_DeadCalm-LucileSmith-FULL-V2.mxf-audio.mp3', // an mp3 file
|
||||
textTracks: [], // empty text track list
|
||||
},
|
||||
{
|
||||
description: 'BigBugBunny sideLoaded subtitles',
|
||||
// sideloaded subtitles wont work for streaming like HLS on ios
|
||||
@@ -100,11 +115,19 @@ export const srcAllPlatformList = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
description: '(mp4) big buck bunny With Ads',
|
||||
ad: {
|
||||
adTagUrl:
|
||||
'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=',
|
||||
},
|
||||
uri: 'https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
|
||||
},
|
||||
];
|
||||
|
||||
export const srcIosList = [];
|
||||
export const srcIosList: SampleVideoSource[] = [];
|
||||
|
||||
export const srcAndroidList = [
|
||||
export const srcAndroidList: SampleVideoSource[] = [
|
||||
{
|
||||
description: 'Another live sample',
|
||||
uri: 'https://live.forstreet.cl/live/livestream.m3u8',
|
||||
@@ -126,12 +149,6 @@ export const srcAndroidList = [
|
||||
uri: 'http://www.youtube.com/api/manifest/dash/id/bf5bb2419360daf1/source/youtube?as=fmp4_audio_clear,fmp4_sd_hd_clear&sparams=ip,ipbits,expire,source,id,as&ip=0.0.0.0&ipbits=0&expire=19000000000&signature=51AF5F39AB0CEC3E5497CD9C900EBFEAECCCB5C7.8506521BFC350652163895D4C26DEE124209AA9E&key=ik0',
|
||||
type: 'mpd',
|
||||
},
|
||||
{
|
||||
description: '(mp4) big buck bunny With Ads',
|
||||
adTagUrl:
|
||||
'https://pubads.g.doubleclick.net/gampad/ads?iu=/21775744923/external/vmap_ad_samples&sz=640x480&cust_params=sample_ar%3Dpremidpostoptimizedpodbumper&ciu_szs=300x250&gdfp_req=1&ad_rule=1&output=vmap&unviewed_position_start=1&env=vp&impl=s&cmsid=496&vid=short_onecue&correlator=',
|
||||
uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
|
||||
},
|
||||
{
|
||||
description: 'WV: Secure SD & HD (cbcs,MP4,H264)',
|
||||
uri: 'https://storage.googleapis.com/wvmedia/cbcs/h264/tears/tears_aes_cbcs.mpd',
|
||||
@@ -157,13 +174,12 @@ export const srcAndroidList = [
|
||||
},
|
||||
];
|
||||
|
||||
// poster which can be displayed
|
||||
export const samplePoster =
|
||||
'https://upload.wikimedia.org/wikipedia/commons/1/18/React_Native_Logo.png';
|
||||
const platformSrc: SampleVideoSource[] = isAndroid
|
||||
? srcAndroidList
|
||||
: srcIosList;
|
||||
|
||||
export const srcList: SampleVideoSource[] = srcAllPlatformList.concat(
|
||||
isAndroid ? srcAndroidList : srcIosList,
|
||||
);
|
||||
export const srcList: SampleVideoSource[] =
|
||||
platformSrc.concat(srcAllPlatformList);
|
||||
|
||||
export const bufferConfig: BufferConfig = {
|
||||
minBufferMs: 15000,
|
||||
|
@@ -102,9 +102,15 @@ const styles = StyleSheet.create({
|
||||
borderWidth: 1,
|
||||
borderColor: 'red',
|
||||
},
|
||||
IndicatorStyle: {
|
||||
flex: 1,
|
||||
indicatorContainer: {
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
gap: 10,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
indicatorText: {
|
||||
color: 'white',
|
||||
},
|
||||
seekbarContainer: {
|
||||
flex: 1,
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import {Drm, ReactVideoSource, TextTracks} from 'react-native-video';
|
||||
|
||||
export type AdditionalSourceInfo = {
|
||||
textTracks: TextTracks;
|
||||
adTagUrl: string;
|
||||
description: string;
|
||||
drm: Drm;
|
||||
noView: boolean;
|
||||
textTracks?: TextTracks;
|
||||
adTagUrl?: string;
|
||||
description?: string;
|
||||
drm?: Drm;
|
||||
noView?: boolean;
|
||||
};
|
||||
|
||||
export type SampleVideoSource = ReactVideoSource | AdditionalSourceInfo;
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user