how to autoplay youtube embedded video in react native? - react-native

I am trying to autoplay the youtube embedded video in my react native app.
here is my code,
render() {
const { data } = this.props;
const { loading } = this.state;
return (
<View>
<CloseButton onTrigger={this.closeModal.bind(this)} />
<PlayIcon onTrigger={this.playVideo} />
<Image source={{uri:data.src}} resize='contain' style={{height:250}} />
<Image
source={require('../../assets/img/grediant.png')}
resizeMode='cover' style={styles.gradientImage} />
<ContentWidget style={styles.infoContentTwo}>
<MyAppText style={{color:'white'}}>{data.title}</MyAppText>
</ContentWidget>
{this.state.openVideo && <View style={styles.webViewStyle}>
<WebView style={{height:250}} source={{uri:`${data.video}?autoplay=1`}} fullScreen={true} />
</View>}
{loading && <Spinner />}
</View>
);
}
but it's not working, I have a playIcon custom button, if I click that button then youtube video should play. I don't know where I am wrong in the code.

You can user react-native-youtube for embedding youtube video to your react native project. You can configure the property to autoplay the video.
<YouTube
videoId="KVZ-P-ZI6W4" // The YouTube video ID
play={true} // control playback of video with true/false
onReady={e => this.setState({ isReady: true })}
onChangeState={e => this.setState({ status: e.state })}
onChangeQuality={e => this.setState({ quality: e.quality })}
onError={e => this.setState({ error: e.error })}
style={{ alignSelf: 'stretch', height: 300 }}
/>

Related

Videos play at the same time - React Native

I have two videos from https://www.npmjs.com/package/react-native-video
I do not have the controls active, my intention is to activate and deactivate the videos by pressing buttons. I do it with states, my problem is that when I press a button to pause or play a video, all of them play, not just one.
I have a list of videos in a JSON and iterate through all of them.
Here is a snippet of my code:
const [paused, setPaused] = useState(false);
const playVideo = () => {
setPaused(!paused);
}
{videos.map((video) => (
<Video
source={{ uri: video.video }}
rate={1.0}
volume={1.0}
resizeMode="cover"
style={styles.video}
paused={paused}
onEnd={() => setPaused(true)}
/>
{paused && (
<View style={styles.videoPause}>
<Text style={styles.title}>{video.titulo}</Text>
<Text style={styles.description}>{video.descripcion}</Text>
<TouchableOpacity style={styles.playButton} onPress={() => playVideo()}>
<CustomIcon name="play" size={90} color={'#fff'} />
</TouchableOpacity>
</View>
)}
))}
The problem is with your state, you should make a component to wrap the Video and manage play/pause state in there. This way you can control every video individually.
First create a component which has independent state and not global as you have it here.
Example:
export default function VideoPlayer(props) {
const { styles, video } = props
const [paused, setPaused] = useState(false)
const playVideo = () => {
setPaused(!paused)
}
return (
<View>
<Video
paused={paused}
rate={1.0}
resizeMode="cover"
source={{ uri: video.video }}
style={styles.video}
volume={1.0}
onEnd={() => setPaused(true)}
/>
{
paused && (
<View style={styles.videoPause}>
<Text style={styles.title}>{video.titulo}</Text>
<Text style={styles.description}>{video.descripcion}</Text>
<TouchableOpacity style={styles.playButton} onPress={() => playVideo()}>
<CustomIcon color="#fff" name="play" size={90} />
</TouchableOpacity>
</View>
)
}
}
)
and then render it in your page like this:
{videos.map((video) => <VideoPlayer styles={...YOUR_STYLES} video={video}/>}
You can also declare the styles inside the component if you prefer but then you wont need to pass them as props.

How to play a video with react native video and pause other in flatlist

I am making a video app like tiktok / instagram reel and i have a flatlist as below
All my videos play automatically and i have it set so that its paused on render (at the moment), I am tying to play a video when it is visible on the screen and pause the other vodeos, but it doesn't work i can't seem to see anything online on how i can pause the other videos or possibly just render one video until i scroll but all videos are set to true no matter what i do.
how can i get the video that is visible to play and then pause when user scrolls and then play the other visible video?
I have been at this for 2 days and my head is Fried, any help would be appreciated :(
PostScreen.js
const [state, setState] = useState({
isVisible: false,
})
const videoData [
{
id: 1,
video: videourl
},
{
id: 2,
video: videourl
},
];
const _onViewableItemsChanged = useCallback(({ viewableItems }) => {
if(viewableItems[0]){
if(viewableItems[0].isViewable){
setState({...state, isVisible: true})
}
}
}, []);
const _viewabilityConfig = {
itemVisiblePercentThreshold: 50
}
<FlatList
data={videosData}
decelerationRate={'fast'}
showsVerticalScrollIndicator={false}
snapToInterval={Dimensions.get('window').height}
snapToAlignment={"start"}
initialScrollIndex={0}
disableIntervalMomentum
onViewableItemsChanged={_onViewableItemsChanged}
viewabilityConfig={_viewabilityConfig}
renderItem={ ({ item }) => (
<View>
<VideoPlayerComponent data={item} />
</View>
)}
/>
VideoPlayerComponent
const [data] = useState(props.data)
const [paused, setPaused] = useState(true);
return(
<View>
<TouchableWithoutFeedback
onPress={() => setPaused(!paused)}
>
<View>
<Video
style={styles.fullScreen}
source={data.video}
resizeMode="cover"
paused={paused}
repeat
/>
{
paused ? (
<View style={styles.pausedIcon}>
<Icon name="play" type="ionicon" color="white" size={68} />
</View>
): null
}
</View>
</TouchableWithoutFeedback>
</View>
)
friends I have solved the issue for my react native video project.
the issue was that all videos are playing in Flatlist but we need to play only singal video on the current viewport and pause the rest.
just do the following steps to solve all videos playing issue
1: npm install #svanboxel/visibility-sensor-react-native
2: import VisibilitySensor from '#svanboxel/visibility-sensor-react-native'
3: do this
import VisibilitySensor from '#svanboxel/visibility-sensor-react-native'
const video = ()=>{
const [paused, setpaused] = useState(true)
return(
<VisibilitySensor onChange={(isVisible)=>{
return(
console.log(isVisible),
isVisible?setpaused(false):setpaused(true)
)
}
}
>
<View>
<Video
source={{uri: 'https://d8vywknz0hvjw.cloudfront.net/fitenium-media-prod/videos/45fee890-a74f-11ea-8725-311975ea9616/proccessed_720.mp4'}}
style={styles.video}
onError={(e) => console.log(e)}
resizeMode={'cover'}
repeat={true}
paused={paused}
/>
</View>
</VisibilitySensor>
)
}
4: I have just given you the basic structure you can add styling stuff as your requirements.
5: remember that always add your view/video elements between the VisibilitySensor tags, otherwise it will not work.
6: this code will give you true when your video component will render in flatlist viewport and remainig will give you false. with this you can manage play/pause state of video element.
thanks...
I managed to use the inviewport library
using this snippiti managed to convert to functional class
in my functional class i just passed a flatlist as it was.
<FlatList
data={videos}
decelerationRate={'fast'}
showsVerticalScrollIndicator={false}
snapToInterval={Dimensions.get('window').height}
snapToAlignment={"start"}
initialScrollIndex={0}
disableIntervalMomentum
renderItem={ ({ item }) => (
<View>
<VideoPlayerComponent data={item}/>
</View>
)}
/>
then in my VideoPlayerComponent i do this
const video = useRef(ref)
const playVideo = () => {
if(video) {
setPaused(false);
}
}
const pauseVideo = () => {
if(video) {
setPaused(true);
}
}
const handlePlaying = (isVisible) => {
isVisible ? playVideo() : pauseVideo();
}
return (
<View>
<Video
ref={ ref => {video.current = ref}}
style={styles.fullScreen}
source={data.video}
paused={paused}
resizeMode="cover"
repeat
/>
</View>
)
This will play the video that is in. view and will pause the other based on the ref passed to it.
Hope this helps anyone stuck as i was stuck for a few days :)

Autoplay video on element focus in react-native

import {Video} from 'expo-av';
return (
<FlatList
data={videos}
// keyExtractor={(item,ind}
keyExtractor={(item) => item.names}
renderItem={({item})=>(
<TouchableOpacity
onPress={() => {console.log('pushed');navigation.push('Details',{url:item.videourl})}}>
<Video
usePoster="true"
source={{ uri: item.videourl }}
rate={1.0}
volume={1.0}
isMuted={false}
resizeMode="cover"
shouldPlay={isFocused ? true : false}
// isLooping
// useNativeControls
posterSource={{uri:item.imageurl}}
style={{ height: 300 }}
/>
</TouchableOpacity>
)}/>
);
If one video gets focused then the video must be played and if the video is not focused then it should pause.I am using expo-av for playing video. The above code is playing all videos on the screen but I want to play the video which is focused just like what youtube does.
To do this you need to keep track of how the scrollview has moved (the offset). FlatList has an onScroll property, where the callback is given information about the list layout etc., and you are interested in tracking how much the content has been scrolled vertically - that is contentOffset.y.
Dividing this value by the list item height (a constant 300 in your case) and rounding will give you the index of the item that should be playing.
Use state to store the currently focused index:
const [focusedIndex, setFocusedIndex] = React.useState(0);
Add a handler for the onScroll event :
const handleScroll = React.useCallback(({ nativeEvent: { contentOffset: { y } } }: NativeSyntheticEvent<NativeScrollEvent>) => {
const offset = Math.round(y / ITEM_HEIGHT);
setFocusedIndex(offset)
}, [setFocusedIndex]);
Pass the handler to your list:
<FlatList
onScroll={handleScroll}
...
/>
and modify the video's shouldPlay prop:
<Video
shouldPlay={focusedIndex === index}
...
/>
You can see a working snack here: https://snack.expo.io/#mlisik/video-autoplay-in-a-list, but note that the onScroll doesn't seem to be called if you view the web version.
Try https://github.com/SvanBoxel/visibility-sensor-react-native
Saved my time. You can use it like.
import VisibilitySensor from '#svanboxel/visibility-sensor-react-native'
const Example = props => {
const handleImageVisibility = visible = {
// handle visibility change
}
render() {
return (
<View style={styles.container}>
<VisibilitySensor onChange={handleImageVisibility}>
<Image
style={styles.image}
source={require("../assets/placeholder.png")}
/>
</VisibilitySensor>
</View>
)
}
}

How do I pause a playing video (played with react-native-video) when user scrolls to another page in a viewpager (#react-native-community/viewpager)?

In my app I am using a ViewPager (#react-native-community/viewpager) to display several pages. Some of these pages contain videos that I am displaying using react-native-video. If I start a video on one page and then scroll to the next page the video keeps playing in the background. The user can hear the audio of the video although the audio is not visible.
I would like to pause the video when the user scrolls to the next page, how do I accomplish that?
You can store the current page value in state and set some indexes to your pages, like in example below. After that just check if your page is current page:
<ViewPager
initialPage={0}
onPageScroll={({ nativeEvent }) => {
this.setState({
activePage: nativeEvent.position
})
}
}>
<View key="1">
<Video source={{ uri: '' }}
paused={this.state.activePage !== 0} />
</View>
<View key="2">
<Video source={{ uri: '' }}
paused={this.state.activePage !== 1} />
</View>
</ViewPager>
EDIT:
If you do not need the video to auto-start, you can add isPlaying property in state, and set it to true when you need.
<ViewPager
initialPage={0}
onPageScroll={({ nativeEvent }) => {
this.setState({
activePage: nativeEvent.position,
isPlaying: false
})
}
}>
<View key="1">
<Video source={{ uri: '' }}
paused={!this.state.isPlaying || this.state.activePage !== 0} />
</View>
<View key="2">
<Video source={{ uri: '' }}
paused={!this.state.isPlaying || this.state.activePage !== 1} />
</View>
</ViewPager>
You can check index of ViewPage with index of VideoItem when you map data.
Example:
<ViewPager
onPageSelected={this.onPageSelected}
initialPage={currentVisibleIndex}
style={{ width: '100%', height: '100%', justifyContent: 'center' }}
key={data.length}
// onPageScroll={this.onPageScroll}
scrollEnabled={data && data.length > 1}
// onPageScrollStateChanged={this.onPageScrollStateChanged}
>
{data.map((item, i) => {
if (isVideo(item)) {
return (
<VideoItem
uri={item}
key={i.toString()}
currentVisibleIndex={currentVisibleIndex}
currentIndex={i}
/>
);
}
return (
<ImageItem
uri={item}
defaultSource={Images.defaultImageAlbum}
key={i.toString()}
/>
);
})}
</ViewPager>
And in VideoItem.js you can use this to paused video when you scroll viewpager.
static getDerivedStateFromProps(props, state) {
let { paused } = state;
if (props.currentVisibleIndex !== props.currentIndex) {
paused = true;
}
return {
paused,
currentVisibleIndex: props.currentVisibleIndex
};
}
Sorry about my English.

Pausing videos on FlatList horizontal when swiping

I'm able to console log the viewable items, when swiping when using FlatList, but I was wondering how I can manage pausing the video. Or if there's a better way in doing so?
This is the RenderItem function component
const RenderItem = (props) => {
const [paused, setPaused] = useState(true);
const togglePlay = () => setPaused(prev => !prev);
return (
<View>
{props.is_video ? (
<>
<Video
paused={paused}
repeat
source={{uri: props.mediaUrl}}
/>
<TouchableWithoutFeedback onPress={togglePlay}>
<View>
{paused ? <Icon
size={180}
name="play"
type="FontAwesome"
style={{opacity: 0.7, color: '#cccccc'}}
/> : null}
</View>
</TouchableWithoutFeedback>
</>
) : (
<Image source={{uri: props.mediaUrl}} />
)}
</View>
);
};
Then in another function, I have this:
const Post = (props) => {
const onViewRef = useRef((viewableItems)=> {console.log(viewableItems)});
const viewConfigRef = useRef({ viewAreaCoveragePercentThreshold: 50 });
return (
<View style={{flex: 1}}>
<View>
<FlatList
onViewableItemsChanged={onViewRef.current}
viewabilityConfig={viewConfigRef.current}
data={props.navigation.state.params.media}
snapToAlignment={'center'}
horizontal
decelerationRate={'fast'}
pagingEnabled
renderItem={({item}) => <RenderItem {...item} />}
keyExtractor={item => item.mediaUrl}
/>
</View>
</View>
);
};
I'm able to press the video and it'll Play or Pause. When I'm swiping right now, the videos continue to play. I want to be able to ensure that when swiping, the video played will become paused now.
You can lift the pause/playing state to the parent component (Post). Since at most 1 video should be playing at anytime, the state can simply store the item ID (or mediaUrl if you are using that as the key/ID) that is currently playing.
In RenderItem:
<Video paused={props.paused} ... />
<TouchableWithoutFeedback onPress={props.onTogglePlay}>
In Post (you can use useCallback for the anonymous functions):
const [activeVideo, setActiveVideo] = useState(null);
...
<FlatList onViewableItemsChanged={() => setActiveVideo(null)} .../>
...
<RenderItem
paused={activeVideo !== item.mediaUrl}
onTogglePlay={() =>
setActiveVideo(item.mediaUrl === activeVideo ? null : item.mediaUrl)
}
{...item}
/>
You may also store the ref to the active video and pause the video through that ref.