react-nativeexporeact-native-webexpo-av

Why will my expo-av Video not start playing automatically?


I have a Video that I am rendering with expo-av. The video renders fine, however it will not start playing upon first render. I have the shouldPlay prop set to true. I have provided a snack example here as well as some code below. If you use the snack example, please set the simulator to web.

Why does the video not start playing automatically?

      <Video
        style={{width: 500, height: 300, resizeMode: 'contain'}}
        source={{
          uri: 'https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
        }}
        resizeMode={ResizeMode.CONTAIN}
        shouldPlay={true}
        videoStyle={{width: 500, height:300}}
      />

Solution

  • Adding to the correct reason given by VonC, we have Autoplay policy in Chrome and Chromium Autoplay. AutoPlay Policy may vary from browser to browser, but in most cases it atleast requires a user interaction. Also if audio is muted, then there's a high probability of auto play. The article explains the reason why most of the video streaming websites we see today are muted. The video is muted,if browser supports it will be auto played, if it doesn't, then if the user unmutes it, then it automatically plays.

    In short, we have to keep the audio muted and place a mute/unmute button on the screen.
    The styling is poor in this demo, but it atleast give an idea on how to proceed further.
    The code is provided below and there's also snack example.

     // App.js
    import * as React from 'react';
    import { View, StyleSheet, Button } from 'react-native';
    import { Video, ResizeMode } from 'expo-av';
    import {useEffect, useState} from "react";
    
    export default function App() {
        const video = React.useRef(null);
        const playerButton = React.useRef(null);
        const [isMuted, setIsMuted] = useState(true);
        const [status, setStatus] = React.useState({});
        const styles = StyleSheet.create({
            container: {
                alignItems:"center",
                justifyContent: "center",
                height: "100%",
                width:"100%"
            },
            video: {
                height: "380px",
                width: "400px"
            },
            buttons: {
                display:"flex",
                width: "500px",
                flexDirection: "row",
                padding:0,
                margin:0,
                justifyContent: "flex-start",
                marginLeft:"200px"
            },
            spacing: {
              marginRight: "16px",
            }
        });
    
        useEffect(()=> {
    
        },[])
    
        return (
            <View style={styles.container}>
                <Video
                    ref={video}
                    style={styles.video}
                    source={{
                        uri: 'https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
                    }}
                    autoPlay
                    useNativeControls
                    resizeMode={ResizeMode.CONTAIN}
                    shouldPlay={true}
                    isMuted={isMuted}
                    onPlaybackStatusUpdate={status => setStatus(() => status)}
                />
                <View style={styles.buttons}>
                    <Button
                        style={styles.button}
                        ref={playerButton}
                        title={status.isPlaying ? 'Pause' : 'Play'}
                        onPress={() =>
                            status.isPlaying ? video.current.pauseAsync() : video.current.playAsync()
                        }
                    />
                    <div style={styles.spacing}/>
                    <Button
                        style={styles.button}
                        ref={playerButton}
                        title={isMuted ? 'Unmute' : 'Mute'}
                        onPress={() => setIsMuted(!isMuted)}
                    />
                </View>
            </View>
        );
    }