React Native Youtube Video is not playing if not fullscreen - react-native

I am facing this weird issue, my youtube videos are not playing if the fullscreen is set to false. But if I set it to true, then it works fine. I dont need the full screen. Following is my code
{this.state.showYoutube &&
<YouTube
apiKey="MY-YOUTUBE-API-KEY"
videoId={this.state.videoId} // The YouTube video ID
play={false} // control playback of video with true/false
fullscreen={false} // control whether the video should play in fullscreen or inline
loop={false} // control whether the video should loop when ended
//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})}
onError={e => console.log(e.error)}
style={{alignSelf: 'stretch', height: 300}}
/>
}
if this.state.showYoutube is set to true then Youtube will be shown and the this.state.videoId is set after an api call,
I have used height and removed native base drawer after facing overlaying issue. Then it was working.
But now it is not working again, please tell me what I am doing wrong.

Found the solution here
export default class extends Component {
state = {
height: 215
}
handleReady = () => {
setTimeout(() => this.setState({ height: 216 }), 500);
}
render() {
return (
<YouTube
apiKey = {config.YOUTUBE_API_KEY}
ref = {item => this.player = item}
videoId = {getVideoId(uri)}
controls = {1}
onReady = {this.handleReady}
style = {{ alignSelf: 'stretch', height: height }}
/>
);
}
}
It worked for me, but still there is a known issue which is that if resumed from a full screen, the screen is not auto oriented.

Related

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>
)
}
}

ActivityIndicator while takePictureAsync with Expo Camera

I'm developing a React Native app and I want to show an ActivityIndicator component while the Expo Camera is processing the image.
<TouchableOpacity style={{alignSelf: 'center'}} onPress={takePicture}>
<FontAwesome name="camera" style={{ color: "#FEA428", fontSize: 50, marginBottom: 20}}/>
</TouchableOpacity>
So the function takePicture do this:
const takePicture = async () => {
setLoading(prevState => !prevState)
if(cameraRef){
let photo = await cameraRef.takePictureAsync({quality: 0.5, skipProcessing: true, fixOrientation: false});
setLoading(prevState => !prevState)
setPhotoAbove(photo)
}
}
setLoading change the "isLoading" prop which say if the ActivityIndicator is going to be visible or not. However, after the first setLoading(prevState => !prevState) then the following code is never executed. Am I missing something here?
EDIT: I'm posting an Expo Snack with the code for testing purposes. In Web the problem isn't visible but for example if you run it on Android it will.
https://snack.expo.io/#avradev/0a8a01
Tks.
You should move your second setLoading just after your await method call like this:
const takePicture = async () => {
setLoading(prevState => !prevState)
if(cameraRef){
let photo = await cameraRef.takePictureAsync({quality: 0.5, skipProcessing: true, fixOrientation: false});
setLoading(prevState => !prevState);
setPhotoAbove(photo);
}
}

React Native Expo Video av-expo -- Directly play as fullscreen

I'm trying to do this by react-native using the av-expo video.
What I'm trying to do is to launch the video directly in full screen without going through the "Video" stack (without the double loading of the MediaPlayerScreen stack + the native fullScreen stack).
If the user mutes the full screen by the native fullScreen output button, then we go back directly to a stack
The idea is to use only the native fullscreen stack to display the video. Is this possible?
I don't know if I'm clear, if it can help to understand, here is the code of my MediaPlayerScreen component
export class MediaPlayerScreen extends Component {
static navigationOptions = {
//header: null,
headerTitle: '',
headerTransparent: false,
headerTintColor: 'white',
}
constructor(props) {
super(props)
this.AG = AG.instance
this.filePath =
this.AG.getFilePath() + props.navigation.state.params.file
this.windowWidth = Dimensions.get('window').width
this.windowHeight = Dimensions.get('window').height
}
//
onPlaybackStatusUpdate = (playbackStatus) => {
if (playbackStatus.didJustFinish) {
this.props.navigation.goBack()
}
}
//
_handleVideoRef = async (component) => {
const playbackObject = component
if (playbackObject) {
await playbackObject.loadAsync({
uri: this.filePath,
shouldPlay: false,
posterSource: this.poster,
})
// todo: Trigger fullScreen without videoStack loading
//playbackObject.presentFullscreenPlayer();
playbackObject.playAsync()
//playbackObject.setOnPlaybackStatusUpdate(this.onPlaybackStatusUpdate);
}
}
componentDidMount() {
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE)
}
componentWillUnmount() {
//playbackObject.dismissFullscreenPlayer();
//this.props.navigation.goBack();
ScreenOrientation.lockAsync(
ScreenOrientation.OrientationLock.PORTRAIT_UP
)
}
onFullscreenUpdate = ({ fullscreenUpdate, status }) => {
console.log(fullscreenUpdate, status)
switch (fullscreenUpdate) {
case Video.FULLSCREEN_UPDATE_PLAYER_WILL_PRESENT:
console.log(' the fullscreen player is about to present')
break
case Video.FULLSCREEN_UPDATE_PLAYER_DID_PRESENT:
console.log('the fullscreen player just finished presenting')
break
case Video.FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS:
console.log('the fullscreen player is about to dismiss')
break
case Video.FULLSCREEN_UPDATE_PLAYER_DID_DISMISS:
console.log('the fullscreen player just finished dismissing')
}
}
render() {
return (
<SafeAreaView style={styles.container}>
<Video
ref={this._handleVideoRef}
useNativeControls
rate={1.0}
resizeMode="contain"
onPlaybackStatusUpdate={(playbackStatus) =>
this.onPlaybackStatusUpdate(playbackStatus)
}
onFullscreenUpdate={this.onFullscreenUpdate}
style={{
width: this.windowHeight,
height: this.windowWidth,
}}
/>
</SafeAreaView>
)
}
}
Thanks for your help,
Meums/
hey if I am not getting you wrong you want to load the player fullscreen by default.you can follow this approach:
const videoRef = useRef(null);
<Video
ref={videoRef}
useNativeControls={false}
style={styles.container}
isLooping
source={{
uri: videoUri,
}}
onLoad={()=>{
videoRef?.current?.presentFullscreenPlayer();
}
resizeMode="contain"
onPlaybackStatusUpdate={(status) => setStatus(() => status)}
/>

React Native Expo Video av-expo

I'm trying to do this in react native using av-expo.
When the button is pressed, a video component is rendered in fullscreen mode, portrait orientation.
When exiting from fullscreen, the video component is hidden.
I'm not able to:
show it in fullscreen mode
detect the exiting event from the fullscreen mode.
function showVideo(){
<Video
source={{ uri:'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
resizeMode="cover"
useNativeControls
style={{ width: 300, height: 300 }}/>
}
export default function App(){
const[state,setState]=useState(0)
return(
<View>
{state ? showVideo() : null}
<Button onPress={=>(setState(1)}/>
<View>
)
}
Would anyone please help me?
Since you use av-expo; there are FullScreen APIs for you.
The following methods are available on the component's ref:
videoRef.presentFullscreenPlayer(); use this to present Video in the fullscreen mode.
videoRef.dismissFullscreenPlayer()
and use onPlaybackStatusUpdate, a function to be called regularly with the onFullscreenUpdate, a function to be called when the state of the native iOS fullscreen view changes (controlled via the presentFullscreenPlayer() and dismissFullscreenPlayer() methods on the Video's ref.
export default class App extends React. Component{
_videoRef;
showVideoInFullscreen = async () => {
// PlaybackStatus https://docs.expo.io/versions/latest/sdk/av/
const status = await this._videoRef.presentFullscreenPlayer();
console.log(status)
}
dismissVideoFromFullscreen = async () => {
const status = await this._videoRef.dismissFullscreenPlayer();
console.log(status);
}
onFullscreenUpdate = ({fullscreenUpdate, status}) => {
console.log(fullscreenUpdate, status)
switch (fullscreenUpdate) {
case Video.FULLSCREEN_UPDATE_PLAYER_WILL_PRESENT:
console.log(' the fullscreen player is about to present');
break;
case Video.FULLSCREEN_UPDATE_PLAYER_DID_PRESENT:
console.log('the fullscreen player just finished presenting');
break;
case Video.FULLSCREEN_UPDATE_PLAYER_WILL_DISMISS:
console.log('the fullscreen player is about to dismiss');
break;
case Video.FULLSCREEN_UPDATE_PLAYER_DID_DISMISS:
console.log('the fullscreen player just finished dismissing');
}
}
render () {
return (
<View style={styles.container}>
<Video
ref={(ref) => (this._videoRef = ref)}
source={{ uri: 'http://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4' }}
resizeMode="cover"
useNativeControls
onFullscreenUpdate={this.onFullscreenUpdate}
style={{ width: 300, height: 300 }}
/>
<Button
title={'show video'}
onPress={() => {
this.showVideoInFullscreen();
}}
/>
</View>
);
}
}
output
the fullscreen player is about to present
the fullscreen player just finished presenting
the fullscreen player is about to dismiss
the fullscreen player just finished dismissing