Browser video flickers when switching clip [HTML, JS] - javascript

I want to have video clips that seamlessly transition from one to another(with idle animations). For starters, I wanted to use the normal browser player and just switch sources when one clip ends like this:
var videos = [
"video/1.webm",
"video/2.webm",
"video/3.webm",
"video/4.webm",
];
let i = 0;
const videoCount = videos.length;
const element = document.getElementById("video");
element.addEventListener('ended', myHandler, false);
function myHandler() {
i++;
if (i == videoCount) {
i = 0;
}
element.setAttribute("src", videos[i]);
element.autoplay = true;
// element.preload = true;
// element.muted = true;
element.load();
}
The problem is that there is a stutter/flicker or delay before a new clip starts playing(in chrome and firefox). The clips I have don't contain any black or empty frames(clips I have loop fine).
As far as I can tell it shows a blank screen for a frame or two.
Is there any way to preload the clips so they switch instantaneously?

The comments from Will and VC.One were leading me onto the right path. I created 2 video elements and instead of pushing and pulling the z-index I pushed it off screen with:
.hidden {
position: absolute;
left: -100vw;
}
I ended up using this:
var videos = [
"video/v1.webm",
"video/v2.webm",
"video/v3.webm",
// ...
];
var i = 0;
const videoCount = videos.length;
const v1 = document.getElementById("video");
const v2 = document.getElementById("video2");
v1.muted = true;
v2.muted = true;
v1.setAttribute("src", videos[i]);
v1.load();
v1.play();
i++;
v2.setAttribute("src", videos[i]);
v2.load();
v1.addEventListener('ended', vHandler, false);
v2.addEventListener('ended', vHandler, false);
function vHandler() {
if((i+1) == videoCount)
i = 0;
if(i % 2 == 0) {
i++;
v2.setAttribute("src", videos[i]);
v2.load();
v1.classList.remove("hidden");
v2.classList.add('hidden');
v1.play();
} else {
i++;
v1.setAttribute("src", videos[i]);
v1.load();
v2.classList.remove("hidden");
v1.classList.add('hidden');
v2.play();
}
}

Related

How to randomly (and seamlessly) display several background videos on an endless loop using JavaScript

Here is what I want to achieve: I've got a bunch of clips in an array and I want all of them to be displayed randomly and seamlessly (using preload options) as background videos. I took some code that I found in another post and so far I've been able to make the first video to be chosen randomly, but then the rest of them keep displaying in order (as included in the array). How would you modified this code so all of them –and not only the first one– are displayed randomly? I guess it should be pretty easy to solve this problem to most of you but I am not a programmer so it would be great if any of you could help me. Thanks in advance. Here is my current code:
<script>
var videoContainer = document.getElementById('videoContainer'),
output = document.getElementById('output'),
nextVideo,
videoObjects =
[
document.createElement('video'),
document.createElement('video')
],
vidSources =
[
"clip1.mov",
"clip2.mov",
"clip3.mov",
"clip4.mov",
],
nextActiveVideo = Math.floor((Math.random() * vidSources.length));
videoObjects[0].inx = 0;
videoObjects[1].inx = 1;
initVideoElement(videoObjects[0]);
initVideoElement(videoObjects[1]);
videoObjects[0].autoplay = true;
videoObjects[0].src = vidSources[nextActiveVideo];
videoContainer.appendChild(videoObjects[0]);
videoObjects[1].style.display = 'none';
videoContainer.appendChild(videoObjects[1]);
function initVideoElement(video)
{
video.playsinline = true;
video.muted = false;
video.preload = 'auto';
video.onplaying = function(e)
{
nextActiveVideo = ++nextActiveVideo % vidSources.length;
if(this.inx == 0)
nextVideo = videoObjects[1];
else
nextVideo = videoObjects[0];
nextVideo.src = vidSources[nextActiveVideo];
nextVideo.pause();
};
video.onended = function(e)
{
this.style.display = 'none';
nextVideo.style.display = 'block';
nextVideo.play();
};
}
</script>
<body>
<div id="videoContainer"></div>
</body>
video {
object-fit: cover;
width: 100vw;
height: 100vh;
position: fixed;
top: 0;
left: 0;
}
#videoContainer {
display: inline-block;
}
maybe in the video.onended, first do nextActiveVideo = Math.floor((Math.random() * vidSources.length)); again.
so you can accapet it :)

How to pause previous audio function?

When I press the button, I want to play a song, when I press the second song a second time, and when the third one, the cycle repeats again, but the first song is shorter than the second one, and if you click many times, the long song plays simultaneously with its other copy. Is it possible to stop the previous music and move on to another?
Html:
< a id="Play">test< / a>
Script:
window.onload=function(){
let number = 0;
var t;
document.getElementById('Play').addEventListener('click',function(){
let audio = new Audio();
if ( number == 0 ) {
audio.src = '/assets/sound/test.mp3';
number = 1;
}
else
if ( number == 1 ) {
audio.src = '/assets/sound/curious&loony.mp3';
number = 0;
}
audio.autoplay = true;
});
}
sound.pause();
sound.currentTime = 0;
Use this for pause audio
Found a way.
How to:
<script>
var i = 1, player = new Audio();
player.src = "/assets/sound/sound1.mp3";
document.querySelector('#play-button').addEventListener('click', function(e) {
e.preventDefault();
if (i === 1) {
player.src = "/assets/sound/sound1.mp3";
i = 0;
} else if (i === 0) {
player.src = "/assets/sound/sound2.mp3";
i = 1;
}
player.play();
});
</script>
Play me harder

control video playlist with global variables

I have a video playlist that plays videos one after a time.
I need the playlist to continue until it reaches a video with the name loop, and loop the video until one of the global variables lvl1_win or lvl2_loose (from a different script) turn 1.
Depending on the result, play a different playlist, playlist_lvl2 or playlist_lvl1_gameover
This is the Playlist I am currently using. It simply loops the videos one after a time:
var activeloop;
var myvid = document.getElementById('intro_lvl1');
myvid.addEventListener('ended', function (e)
{
var activesource = document.querySelector("#intro_lvl1 source.active");
var nextsource = document.querySelector("#intro_lvl1 source.active +
source") ||
document.querySelector("#intro_lvl1 source:first-child");
//for the video with the name "loop" in it.
var loopsource = document.querySelector("#intro_lvl1 source.loop");
activesource.className = "";
nextsource.className = "active";
myvid.src = nextsource.src;
myvid.play();
});
Could anybody give me a few suggestions on how to implement this?
You can use RegExp.prototype.test() to check if the .src contains "loop", set .loop to true
if (/loop/.test(nextsource.src)) {
// perform logic here
if (myvid.loop != true) {
myvid.loop = true
};
if (lvl1_win == 1 || lvl2_loose == 1) {
// do other stuff
}
}
Thank you for your answer!
I got it to work with the following:
var lvl1_win;
var lvl1_loose;
var myvid = document.getElementById('intro_lvl1');
myvid.addEventListener('ended', function (e) {
var activesource = document.querySelector("#intro_lvl1 source.active");
var nextsource = document.querySelector("#intro_lvl1 source.active +
source") || document.querySelector("#intro_lvl1 source:first-child");
if (/loop/.test(nextsource.src)) {
if (myvid.loop != true) {
myvid.loop = true;
};
if (lvl1_win == 1) {
alert("Won level 1");
}
if (lvl1_loose == 1) {
alert("Gameover level 1");
}
} else {
activesource.className = "";
nextsource.className = "active";
myvid.src = nextsource.src;
myvid.play();
}
});
However, I cannot add the specific video for winning or loosing in the same source, otherwise it would mess up the playlist.
Or is it possible to play the next video with the class loose if lost vise versa?
What I mean:
if (lvl1_loose == 1) {
play next video with class gameover
then play pause video on last frame (ending the cycle)
}

video play loop play another ja

I need a video to play and loop seamlessly a defined number of times, then skip to a next video and loop seamlessly a defined number of times, and so forth until the playlist ends.
In one page, a user defines videos to be played, as well as how many times it will "loop" (or iterate). These are stored using session variables as:
$_SESSION["Exer[" .$x. "]"]
$_SESSION["Reps[" . $x. "]"].
I'm ignoring this aspect (the php stuff) currently
I have code that independently works, one that loops and one that plays playlists, but I can't seem to manage the merger of them together to achieve functionality. The code is as followed:
HTML
<video width="320" height="240" id="myVideo" autoplay="autoplay">
</video>
JavaScript
For looping:
<script>
var iterations = 1;
document.getElementById('iteration').innerText = iterations;
document.getElementById('myVideo').src = "Video/01.mp4";
myVideo.addEventListener('ended', function () {
if (iterations < 3) {
this.currentTime = 0;
this.play();
iterations ++;
document.getElementById('iteration').innerText = iterations;
}
}, true);
</script>
For playlist:
<script>
var videoSource = new Array();
videoSource[0] = "Video/01.mp4";
videoSource[1] = "Video/02.mp4";
videoSource[2] = "Video/03.mp4";
videoSource[3] = "Video/04.mp4";
var i = 0; // define i
var videoCount = videoSource.length;
function videoPlay(videoNum) {
document.getElementById("myVideo").setAttribute("src", videoSource [videoNum]);
document.getElementById("myVideo").load();
document.getElementById("myVideo").play();
}
document.getElementById('myVideo').addEventListener('ended', myHandler, false);
videoPlay(0); // play the video
function myHandler() {
i++;
if (i == (videoCount - 1)) {
i = 0;
videoPlay(i);
} else {
videoPlay(i);
}
}
</script>
Any help is appreciated.
Please check this, this java script code will replay a video for mentioned number of times and then plays next video if exists in playlist:
var eachVdoLoop = 2;
var currentVdoLoop=0;
var videoSource = new Array();
videoSource[0] = "http://www.sample-videos.com/video/mp4/240/big_buck_bunny_240p_1mb.mp4";
videoSource[1] = "https://www.w3schools.com/html/mov_bbb.mp4";
var videoCount = videoSource.length;
var vdoIndex=0;
document.getElementById('myVideo').addEventListener('ended', myHandler, false);
nextVideo();
function myHandler() {
currentVdoLoop++;
if(currentVdoLoop < eachVdoLoop)
{
document.getElementById("myVideo").play();
}
else
{
vdoIndex++;
currentVdoLoop=0;
nextVideo();
}
}
function nextVideo() {
if(vdoIndex == videoSource.length)
{
alert("Playlist ended!!!")
return;
}
document.getElementById("myVideo").setAttribute("src", videoSource[vdoIndex]);
document.getElementById("myVideo").play();
}
An working jsfiddle (fiddle updated)

HTML5 Audio - stop current play when another sound is started

I am using this method to play audio files when you click on an image:
http://jsfiddle.net/v97Kq/3/
function imageSwitch(_imgID, _imgStart, _imgStop, _soundFileMp3, _soundFileOgg) {
this.imgID = _imgID;
this.imgStart = _imgStart;
this.imgStop = _imgStop;
this.song = new Audio();
if (this.song.canPlayType("audio/mpeg"))
this.song.src = _soundFileMp3;
else
this.song.src = _soundFileOgg;
this.song.loop = true;
this.pos = 0;
this.e;
this.change = function () {
if (this.pos == 0) {
this.pos = 1;
document.getElementById(this.imgID).src = this.imgStop;
this.song.play();
} else {
this.pos = 0;
document.getElementById(this.imgID).src = this.imgStart;
this.song.pause();
}
}
}
It works good! - but how can I get it to stop playing the currently playing sound when another link is clicked and another sound begins?
I found this solution to my issue above, works perfectly.
which I eventually found here:
<script>
var currentPlayer;
function EvalSound(soundobj) {
var thissound=document.getElementById(soundobj);
if(currentPlayer && currentPlayer != thissound) {
currentPlayer.pause();
}
if (thissound.paused)
thissound.play();
else
thissound.pause();
thissound.currentTime = 0;
currentPlayer = thissound;
}
</script>

Categories