frame academy

Learn how to create immersive, cross-platform webxr sites.

project 5: using audio, video, and 360 video in your webxr sites

Part 3: 2D video

GIF showing video on a wall in metaverse project.
I hope you also took a crack at the challenge for Part 2! If you do the challenges, you'll be building your own immersive website that works on desktop, mobile, or VR.

Remember that if you have questions or want to share your work-in-progress, feel free to ask in our online community, or on Twitter with the hashtag #frameacademy

the a-video entity

I hope you managed to get your pauser working for the audio, but if not then please let me know in our online community so I can help you out! Now, we're going to dive into video. We're going to start with flat, 2D video and then in the next part we'll get into videospheres. A lot of this work will be familiar to you from the last part when you were working with audio, but there are a few important differences.

Note: Different browsers have different policies about playing video automatically when a site loads. On iOS, for example, Safari won't let videos autoplay as soon as a site is loaded. I personally don't like it too much when videos autoplay on a site because of how so many websites are overrun with autoplaying video ads these days. In this project, I'm going to assume that you don't want video to autoplay and you're going to make a play and pause button so that the user can control playing and pausing the video.

To put a video in your scene, you can use the a-video entity that comes with A-Frame. The attribute we want to set on this a-video entity is the src attribute, and you can set the src to be the id of the video asset that you preloaded into a-assets in Part 1 of this project.

In the starter project, I already uploaded a video to the the Glitch assets folder and preloaded it into a-assets on line 27 of the HTML file. I gave it id="videoclip", so that's what I can set as the src of my new a-video element. I encourage you to use the video that you uploaded! I'm also going to give my video element height, width, position, and rotation attributes. Here's what my new a-video element looks like:

<a-video src="#videoclip" position="-14.9 3 0" rotation="0 90 0" width="5" height="5"></a-video>

I set up the position and rotation of my video so that it shows up on the left wall, next to the music player.

After that, I also nested two other entities inside my a-video element, one that will be a play button and another that will be a pause button. Check it out in the project by looking at the left wall, and see the whole entity in the HTML on lines 121-138. The video won't be playing yet - remember that we aren't trying to have it autoplay (see the yellow note above).

creating the video player component

Instead of doing this entirely from scratch, we can re-use a lot of what we already have in our public/js/audiocontrols.js file on Glitch. You can copy this file right on Glitch by selecting that file, clicking the arrow dropdown on the right, and clicking the "copy" button. When you do that, you can give the copied file a new name. I renamed mine public/js/videocontrols.js

The first thing I did was renamed the components in the file, renaming songplayer to videoplayer on line 1, and renaming songpauser to videopauser. I removed the songstopper component because we won't need it here - we're just doing controls for playing and pausing.

Alright, let's dive into the component itself. If you remember what we did in public/js/audiocontrols.js, we made a reference to the source of the audio by finding the element in our HTML that had the sound component like this:

let audiosource = document.querySelector('#musicpanel');

Now, for referencing the source of the video, we instead need to directly reference the video element stored in a-assets, not our a-video element inside the scene. That video asset has id="videoclip", as we saw above, so we can instead do this in our new videoplayer component (inside the curly braces after init).

let videosource = document.querySelector('#videoclip');

That makes a reference to our video asset that we can use throughout the rest of the component. Once more looking back to our songplayer component in audiocontrols.js, we made this function that, when called, would cause the audio to play:

let musicplay = () => {        
audiosource.components.sound.playSound()        
}

Now, for making the same function for our video, we can use the .play() HTML5 method that is readily available to use with the video element. You can learn more about the methods and properties that you can use with the video HTML element here. I'm also going to change the name of the function to videoplay. Now, I've got this, first making my reference to the video asset and then making a function that, once called, will cause that video asset to play.

let videosource = document.querySelector('#videoclip');        

let videoplay = () => {        
videosource.play();              
 
}

Finally, since we want this function to be called when the user clicks a play button, just as we did with our songplayer component, we need to add an eventListener to this, knowing that we'll be attaching the component to the HTML entity with our play button on it. Here's my eventListener that will cause our videoplay function to be called once the user clicks the play button.

this.el.addEventListener('click', videoplay);

Check out the whole component in the project embedded above in the public/js/videocontrols.js file.

For the final steps, you have to first import your new JavaScript file in the head of your HTML document with a script element, e.g.

<script src="public/js/videocontrols.js"></script>

Then, you actually have to add the videoplayer component we made to the playbutton that we've nested inside the a-video element. I've done that on line 124 of the HTML file in the project embedded above by simply putting the videoplayer attribute on the vidplaybox entity.

Try it out in the project by clicking the play button on the video player on the left wall.

challenge #3: create and use a video pauser component

Just as you did in Challenge #2, I'd like you to try to write a component that controls pausing - but this time for the video, not the audio. This component will look very similar to the one I made above, but instead of the .play() method, you want to use ,pause()

So, create a copy of the videoplayer component (you can do this in the same JavaScript document), rename it, swap in .pause() in place of .play(), rename anything else you need, and then make sure you attach your new component to the pause button entity that's nested inside the a-video entity. In my project above, that entity is on line 130 in the HTML. Test it out, and let us know in the online community if you have any issues!

< go back to part #2
Playing, pausing, and stopping audio
Move on to part #4 >
360 Video / videospheres