Been trying to change the source video of an HTML5 video (after clicking a button). However I run into errors. Code and errors below:
Relevant HTML:
<video id="video2" playsinline controls muted preload="auto" style="z-index: -1; position: absolute;">
<source src="exercise_media/vid_exercise_sample_1.mp4" type="video/mp4" >
</video>
(regarding the z-index stuff - this video plays then is grabbed by a canvas which re-draws it, as part of the overall application. Probably not relevant but figured I'd mention it.)
Relevant Javascript. Initiates the video, plays it fine. It's a little esoteric because I started from someone else's sample.
loadCompanionVideo();
export async function loadCompanionVideo() {
setStatusText('Setting up companion video...');
try {
video2 = await loadVideo2();
} catch (e) {
let info = document.getElementById('info');
info.textContent = '(video player) this device type is not supported yet, ' +
'or this browser does not support video capture: ' + e.toString();
info.style.display = 'block';
throw e;
}
}
async function loadVideo2() {
const video2 = await setupVideo2();
return video2;
}
async function setupVideo2() {
const video2 = document.getElementById('video2');
video2.width = videoWidth2; // some external numbers
video2.height = videoHeight2; // just to customize width and height; works fine
return video2;
}
So this is fine, my first video exercise_media/vid_exercise_sample_1.mp4
plays just fine. However, I want to change the video source to exercise_media/vid_exercise_sample_2.mp4
, same format, located in same folder, etc. (I made sure this video is fine by hard-coding it into the HTML above, and it also plays just fine.)
Here's what I've been trying for changing it:
function buttonFunctionChangeVideoSrc() {
document.getElementById("video2").pause();
//document.getElementById("#video2 > source").src = "exercise_media/vid_exercise_sample_2.mp4";
document.getElementById("video2").src = "exercise_media/vid_exercise_sample_2.mp4";
document.getElementById("video2").load();
document.getElementById("video2").play();
}
To no avail, neither ("#video2 > source").src
nor ("video2").src
work. In the first case, the error is:
Uncaught TypeError: Cannot set property 'src' of null at HTMLButtonElement The video pauses and stays frozen.
In the second case, trying video2.src
directly (same as document.getElementById("video2")
), the error is
Uncaught (in promise) DOMException: Failed to load because no supported source was found.
The video portion of the screen goes white/blank.
Play/pause functionality works fine, so I know I have a valid reference to my video2
object. But I cannot seem to change the source. And I also know that the other source video works just fine, as I can hard-code it into the HTML and play it without issue. But I cannot seem to dynamically switch between them.
Any help is much appreciated.
Adding more of my code to take a look at. Don't worry about the pose stuff, it's for my application to analyze the videos, and works fine when I just have one video side by side the webcam (that's what my application does).
The problem is that I cannot change the video2 source to a different MP4. In fact the only way I can have it play an MP4 at all is if I explicitly set it in the HTML.
HTML:
<div id="canvases" class="canvas-container">
<div id='main' style='display:none'>
<video id="video" playsinline style=" -moz-transform: scaleX(-1);
-o-transform: scaleX(-1);
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
display: none;
">
</video>
<canvas id="output" class="camera-canvas"></canvas>
<canvas id="keypoints" class="camera-canvas"></canvas>
<video id="video2" playsinline controls muted style="z-index: -1; position: absolute;"
>
<source id="source2" src="exercise_media/vid_exercise_sample_1.mp4" type="video/mp4" >
<!-- hard-coding the src in source is the ONLY way I can play a video here at all... -->
</video>
<canvas id="output2" class="camera-canvas2"></canvas>
<canvas id="keypoints2" class="camera-canvas2"></canvas>
<canvas class="illustration-canvas"></cavnas>
<canvas class="illustration-canvas2"></cavnas>
</div>
Javascript:
export async function bindPage() {
setupCanvas();
setupCanvas2();
buttonSetup();
toggleLoadingUI(true);
setStatusText('Loading AI models...');
posenet = await posenet_module.load({
architecture: defaultPoseNetArchitecture,
outputStride: defaultStride,
inputResolution: defaultInputResolution,
multiplier: defaultMultiplier,
quantBytes: defaultQuantBytes
});
setStatusText('Loading FaceMesh model...');
facemesh = await facemesh_module.load();
facemesh2 = await facemesh_module.load();
setStatusText('Loading Avatar file...');
let t0 = new Date();
await parseSVG(Object.values(avatarSvgs)[0]);
setStatusText('Setting up camera...');
try {
video = await loadVideo();
} catch (e) {
let info = document.getElementById('info');
info.textContent = '(web cam) this device type is not supported yet, ' +
'or this browser does not support video capture: ' + e.toString();
info.style.display = 'block';
throw e;
}
try {
video2 = await loadVideo2();
} catch (e) {
console.log("Error loading companion video :: "+e);
}
console.log(video2); // shows the full html
playpauseFunction(); // start video2
toggleLoadingUI(false);
detectPoseInRealTime(video, posenet); //actual application, works fine
}
async function loadVideo2() {
const video2 = await setupVideo2();
return video2;
}
async function setupVideo2() {
const video2 = document.getElementById('video2');
//video2.setAttribute("src", vid_url_1); //does not work
//document.getElementById("source2").src = vid_url_2; // does nothing
videoWidth2orig = video2.videoWidth;
videoHeight2orig = video2.videoHeight; // gives the actual e.g. 640 x 360
//.. I do some stuff below to set video2 width/height, works fine
return video2;
}
function playpauseFunction() {
try {
if (playpause == true) {
video2.pause();
playpause = false;
//alert("Workout paused. Click Play/Pause to resume.");
} else if (playpause == false) {
video2.play();
playpause = true;
}
} catch (e) {
console.log("playpauseFunction exception :: "+e);
}
}
Now, like I said, if I hard-code into HTML the src
of <source>
tag, i.e. <source id="source2" src="exercise_media/vid_exercise_sample_1.mp4" type="video/mp4" >
the application runs fine and looks like the following:
(Works fine, the webcam plays in real-time next to the video, and I have my skeletal tracking running on the rightside video as it plays.)
What I want to do is click on e.g. "Exercise Sample 2" and change the rightside video, obviously. Nothing I've tried has worked, such as:
function setupExercise2() {
video2.setAttribute('autoplay', 'true');
document.getElementById("source2").src = "exercise_media/vid_exercise_sample_2.mp4";
//video2.setAttribute("src", "exercise_media/vid_exercise_sample_2.mp4"); // have tried both, neither work
video2.load();
const playPromise = video2.play() // trigger video load
console.log(playPromise);
if ( playPromise !== undefined ) {
playPromise.then(() => {
// video should start playing as soon as it buffers enough
}).catch(error => {
// playback failed, log error
console.log(error);
})
}
}
Specifically for the first line (uncommented), the console says:
Promise {<pending>}__proto__: Promise[[PromiseState]]: "pending"[[PromiseResult]]: undefined
The right side video turns white and nothing plays. If I try instead with video2.setAttribute
line uncommented, then the console logs:
Promise {<pending>}
__proto__: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: DOMException: Failed to load because no supported source was found.
code: 9
message: "Failed to load because no supported source was found."
name: "NotSupportedError"
__proto__: DOMException
To be clear, I can hard-code in any of the vid_exercise_sample_{2,3,..}.mp4
into the html and they play and run just fine, so I don't believe that's the issue.
Hopefully I've provided a pretty full picture now!
To use JavaScript to dynamically change a video's source, we can set the src property of the source element to the URL of the video. to add the video element with the source element's src attribute set to a video path. to select the source element in the video element with document.
To change source on HTML5 video tag with JavaScript, we an set the src property of the video element. const changeSource = (url) => { const video = document. getElementById("video"); video. src = url; video.
If all you want is really to avoid the width/height to return to defaults (300 x 150) when the next video is loading, you just have to set your <video> 's width and height properties to the ones of the loaded video ( videoWidth and videoHeight are the real values of the media, not the ones of the element).
If your browser error "HTML5 video file not found", it means that your browser is not up to date or website pages does not have a suitable video codec. It would help if you communicated with the developer to solve the issue and install all the required codecs.
The following example code shows a video .src
being updated dynamically.
There are two buttons used to switch between the different sources.
It has been tested on Windows PC using Chrome, Edge and Firefox browsers.
<!DOCTYPE html>
<html><head> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> </head>
<body>
<video id="video2" width="600" height="480" controls style="z-index: 1; overflow:hidden; position: absolute; top: 10px; left: 10px">
<source type="video/mp4">
</video>
<canvas id="myCanvas" width="600" height="480" style="z-index: 1; overflow:hidden; position: absolute; top: 10px; left: 640px">
</canvas>
<div style="z-index: 1; overflow:hidden; position: absolute; top: 510px; left: 10px">
<button onclick="ChangeVideoSrc( 1 )">Play Video 1</button>
<button onclick="ChangeVideoSrc( 2 )">Play Video 2</button>
</div>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var timer_DrawCanvas; //# updated later in code
//# Example video links that work on my testing...
vid_url_1 = "https://seed191.bitchute.com/pupNZR0eMW9M/4CU38o2lkgyj.mp4";
vid_url_2 = "https://seed171.bitchute.com/VBdNMrOHylJh/2BMyQPl6BSpZ.mp4";
//# Try your own links if the above works...
//vid_url_1 = "exercise_media/vid_exercise_sample_1.mp4"
//vid_url_2 = "exercise_media/vid_exercise_sample_2.mp4"
//# Set initial starting vid SRC (used on page load)
const myVid = document.getElementById("video2");
myVid.setAttribute("src", vid_url_1);
//# Setup event listeners
myVid.addEventListener("canplay", handle_Media_Events);
myVid.addEventListener("loadeddata", handle_Media_Events);
myVid.addEventListener("play", handle_Media_Events);
myVid.addEventListener("pause", handle_Media_Events);
myVid.addEventListener("ended", handle_Media_Events);
function drawVideo()
{
ctx.drawImage(myVid, 0, 0, 600, 480);
}
function ChangeVideoSrc( vidNum )
{
myVid.src = window[ "vid_url_" + vidNum ];
myVid.load();
}
function handle_Media_Events()
{
//# if enough data to begin playback
if ( event.type == "canplay" ) { myVid.play(); }
//# if first frame is available
if ( event.type == "loadeddata" )
{ ctx.drawImage( myVid, 0, 0, 600, 480 ); } //# draws re-sized
if ( event.type == "play" )
{ timer_DrawCanvas = setInterval( drawVideo, 30 ); }
if ( (event.type == "pause") || (event.type == "ended") )
{ clearInterval( timer_DrawCanvas ); }
}
</script>
</body>
</html>
Hopefully this will give you a reference point towards achieving the quest of "dynamically change source of the HTML5 Video with Javascript". The quest continues...
Ask anything when you've had chance to test the code.
Just tried out a quick snippet and it works without a bother.. So weird..
what I used
const v = document.getElementById("vid");
const s = document.getElementById("src");
function changeVideo() {
s.src = 'http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4';
v.load();
v.play();
console.log(s,v);
}
document.getElementById("change").onclick=changeVideo;
<video id="vid" controls autoplay style="width:75%">
<source id="src" src="http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4" type="video/mp4">
</video><br/><br/>
<button id="change">Change the video</button>
must be missing something. I'd be able to say for sure if I saw a live example, but that's completely up to you.
Otherwise found this on W3
'Warning: Don't make your function asynchronous with the async keyword. You'll lose the "user gesture token" required to allow your video to play later.'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With