Ad

Play And Pause Video In A-frame And React.js

- 1 answer

My task was play and stop video in videosphere by some action. I has list of element by click on which one video in videosphere should change. I was using React.js and a-frame library. I spent a lot of time to achieve the desired behavior, so I want to share some code and notes. Suddenly someone will be helpful.

Ad

Answer

So some important things:

  • You should play and pause a-video not a-videosphere, on a-videosphere control events don't work
  • You can't stop video, you should use video.currentTime = 0; and then video.pause()
  • You should remove autoplay attribute from video tag and playing it yourself, because if you leave autoplay attribute your audio tracks from the video will be duplicated
  • If you removed autoplay attribute you can't play video before user click event, so you need imitate click event on some element. I created hidden span and imitate click event on that. Article about the problem https://developers.google.com/web/updates/2017/09/autoplay-policy-changes

And pieces of my code:

static getDerivedStateFromProps(nextProps, prevState){
        let update = {};
        if(nextProps.scene_item){
            let isVideoSphere = nextProps.scene_item.type_id === experienceTypes.videosphere;
            update.sceneUrl = nextProps.scene_item.asset_url;
            update.isVideoSphere = isVideoSphere;
            if(isVideoSphere){
                playVideo('scene-video',true)
            }
        }
        return Object.keys(update).length ? update : null;


    }

componentWillUnmount() {
        pauseVideo('scene-video')
    }




export function pauseVideo(id) {
    //pause aframe 360 video
    let video = document.getElementById(id);
    video.currentTime = 0;
    video.pause()
}

export function playVideo(id,first_playing) {
    //play aframe 360 video
    let video = document.getElementById(id);
    let el = document.getElementById('clikable-el-for-play-video');
    if(video){
        if(first_playing){
          if(el){
            el.click()
            video.play()
          }
        }else video.play()
    }
}
<a-scene>
  <a-assets>
    <video id="scene-video" src={sceneUrl} loop/>
  </a-assets>
  <a-videosphere src={'#scene-video'}/>
  <span className="hidden" id="clikable-el-for-play-video"/>
</a-scene>

Update

In safari emit click event doesn't work, so I make the changes:

  • Muted video by default
  • Unmute video by click on HTML element for desktops(I do not need additional button for that so I use div)
  • Unmute video by onTouchEnd event on the same HTML element for mobile devices (If you will use button I think you can skip that)

handleClickOnScene = (event) => {
        let videoId = `scene-video-${this.props.scene_item.id}`;
        let video = document.getElementById(videoId);
        if(video.muted && !video.paused){
            setTimeout(increaseVideoVolume(videoId), 5000)
        }
    }

export function increaseVideoVolume(id,first_playing) {
    let video = document.getElementById(id);
    if(video){
        if(video.muted){
            video.muted = false;
        }
    }
}

Ad
source: stackoverflow.com
Ad