why does this keep playing same video instead of random new video? - javascript

I'm making a random order video player, adapting code from here but the same video just keeps playing, even though I can see (from text above the video) that the random ordering is working. Live version is here.
Is the problem with the appendChild meaning the new video is end of a list but the first in list keeps playing? I tried replaceChild but that didn't work.
<script type="text/javascript">
$(document).ready(function(){
var videos = [
[{type:'mp4', 'src':'carlos/one-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/two-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/three-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/four-carlostest.mp4'}],
[{type:'mp4', 'src':'carlos/five-carlostest.mp4'}]
];
// selecting random item from array as first to be played
var randomitem = videos[Math.floor(Math.random()*videos.length)];
// This function adds a new video source (dynamic) in the video html tag
function videoadd(element, src, type) {
var source = document.createElement('source');
source.src = src;
source.type = type;
element.appendChild(source);
}
// this function fires the video for particular video tag
function newvideo(src){
var vid = document.getElementById("myVideo");
videoadd(vid,src ,'video/ogg');
vid.autoplay = true;
vid.load();
vid.play();
}
// function call
newvideo(randomitem[0].src)
// Added an event listener so that everytime the video finishes ,a new video is loaded from array
document.getElementById('myVideo').addEventListener('ended',handler,false);
function handler(){
var newRandom = videos[Math.floor(Math.random()*videos.length)];
newvideo(newRandom[0].src)
document.getElementById("monitor").innerHTML = "randomitem is " + newRandom[0].src;
}
})
</script>
Also, if anyone can tell me why the autoplay never works that'd be appreciated, though it's the least of my problems.

I have kinda found this solution for your video playing one after other. now in your JS file, now you just will need to add your video src path.
var vidElement = document.getElementById('video');
var vidSources = [
"https://lutins.co.uk/carlos/one-carlostest.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
var activeVideo = Math.floor((Math.random() * vidSources.length));
vidElement.src = vidSources[activeVideo];
vidElement.addEventListener('ended', function(e) {
// update the active video index
activeVideo = (++activeVideo) % vidSources.length;
if(activeVideo === vidSources.length){
activeVideo = 0;
}
// update the video source and play
vidElement.src = vidSources[activeVideo];
vidElement.play();
});
video {
width:350px;
}
<p>wowww you got it!</p>
<video src="https://lutins.co.uk/carlos/one-carlostest.mp4" id="video" autoplay muted playsinline></video>

Change the randomIt variable into a callback, only this way, it will generate new random number each time it get call.
// I have change randomitem into a function with ofcourse a proper name
var getRandomItem = function() {
return videos[Math.floor(Math.random()*videos.length)];
}
You should also call it properly like this:
//newvideo(randomitem[0].src) -> change it to
newvideo(getrandomItem().src)
There might also other adjustments requires for your code to work.

Related

play random video on each visit/refresh with iFrame javascript

How do I create a random video to play every time a user visits/reloads the page with Javascript?
For example, if one person were to go onto my domain, the iFrame would try to load any of the .mp4 files inside of my media file directory where it has like 4 different .mp4 videos. Here is my code below.
Code:
<source src="assets/media/lofi.mp4" type="video/mp4" />
<script type="text/javascript">
const video = document.currentScript.parentElement;
video.volume = 0.15;
function pause_resume() {
const button = document.getElementById("pause_resume_button");
if (video.paused) {
video.play()
button.textContent = "resume video";
} else {
video.pause()
button.textContent = "pause video";
}
}```
You need to use Math.random to choose a random video from a list.
Then add the chosen video url to the html element, and trigger the "play" event.
const videos = ["video1.mp4", "video2.mp4", /* ... */ "video30.mp4"]
const randomNumber = Math.floor(Math.random() * videos.length)
const currentVideo = videos[ randomNumber ]
const videoElement = document.getElementById('video');
videoElement.src = currentVideo
videoElement.play()
Related question: changing source on html5 video tag

How to buffer / preload html5 videos using javascript

I am running the following code which changes the source of an html5 video at the end of each video, so that it constantly plays one video after another. After the first video finishes, it runs the second, then the third and eventually starts again from the beginning, resulting in an endless cycle. It also chooses a random starting point, but that is not important for my question.
In the code below you will only find two video sources but the final code would use around ten or so.
My problem is that there is a small pause between the end of a video and the beginning of the next one. I have made the background-color of the video tag red so that you will be able to see a red flash between the playback of each video.
I'm guessing that this could be solved by preloading all videos specified inside the javascript code. So what I would like to achieve is to preload only the next video in the list specified inside the javascript code when the current video is playing. So when video nr. 5 is playing, it should preload video nr. 6 etc..
Or is this not something that could be solved by effective buffering / preloading? I'm happy about any other suggestions as well..
var vidElement = document.getElementById('video');
var vidSources = [
"http://www.w3schools.com/html/mov_bbb.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
var activeVideo = Math.floor((Math.random() * vidSources.length));
vidElement.src = vidSources[activeVideo];
vidElement.addEventListener('ended', function(e) {
// update the active video index
activeVideo = (++activeVideo) % vidSources.length;
if(activeVideo === vidSources.length){
activeVideo = 0;
}
// update the video source and play
vidElement.src = vidSources[activeVideo];
vidElement.play();
});
video { background-color: red }
<video src="http://www.w3schools.com/html/mov_bbb.mp4" id="video" autoplay muted playsinline></video>
<p>(each video is just ~ 10 seconds)</p>
You can create video elements with preload attribute and add it to div containar like follows:
function initVideoElement(videoEl)
{
videoEl.playsinline = true;
videoEl.muted = false;
videoEl.preload = 'auto'; //but do not set autoplay, because it deletes preload
//loadedmetadata is wrong because if we use it then we get endless loop
videoEl.onplaying = function(e)
{
if(++nextActiveVideo == 2)
nextActiveVideo = 0;
//replace the video elements against each other:
if(this.inx == 0)
nextVideoElement = videoElements[1];
else
nextVideoElement = videoElements[0];
nextVideoElement.src = vidSources[nextActiveVideo];
nextVideoElement.pause();
};
videoEl.onended = function(e)
{
this.style.display = 'none';
nextVideoElement.style.display = 'block';
nextVideoElement.play();
};
}
var videoContainer = document.getElementById('videoContainer'),
nextActiveVideo = 0,
nextVideoElement,
videoElements =
[
document.createElement('video'),
document.createElement('video')
],
vidSources =
[
"http://www.w3schools.com/html/mov_bbb.mp4",
"http://www.w3schools.com/html/movie.mp4"
];
videoElements[0].inx = 0; //set index
videoElements[1].inx = 1;
initVideoElement(videoElements[0]);
initVideoElement(videoElements[1]);
videoElements[0].autoplay = true;
videoElements[0].src = vidSources[0];
videoContainer.appendChild(videoElements[0]);
videoElements[1].style.display = 'none';
videoContainer.appendChild(videoElements[1]);
video{background-color: red}
<div id="videoContainer"></div>

How to switch between 2 audio tracks but 1 video file?

I am a total JavaScript amateur. I want to create a section where people can switch between 2 audios with a video running along with it. I want to show a before and after version of the audio.
Basically, the video should run with the "before" version of the audio initially. Then there should be a button to switch the audio to the "after" version, and go back and forth.
I tried the "audioTracks" method, but the browser compatibility is not good with it. What is the best possible way to achieve it?
Thanks in advance.
You just use two HTML Audio elements and then sync their times:
var audio1 = new Audio()
var audio2 = new Audio()
audio1.src = 'pathToSource',
audio2.src = 'pathToSource2',
var video = document.getElementByID('myvideo');
video.muted = true; //mute video cuz we have audio already
function switchAudio(one, two, vid) {
if(one.paused) {
two.pause();
one.currentTime = vid.currentTime;
one.play
} else {
one.pause();
two.currentTime = vid.currentTime;
two.play()
}
}
That did it :) I made some changes though. The audio seems to be working great. I could play and switch it. But the video was not starting up with the button. So I changed the code to this:
function switchAudio(one, two, vid) {
if (one.paused) {
two.pause();
vid.play();
one.play();
one.currentTime = vid.currentTime;
} else {
vid.pause();
one.pause();
vid.play();
two.play();
two.currentTime = vid.currentTime;
}
}
After this the video is playing along with the audio. But when I switch the audio, their timing does not match. The audio seems to be playing just a little bit late.

How to force a media to be loaded at run time, without playing it now?

I am making a web app that can be open for a long time. I don't want to load audio at load time (when the HTML gets downloaded and parsed) to make the first load as fast as possible and to spare precious resources for mobile users. Audio is disabled by default.
Putting the audio in CSS or using preload is not appropriate here because I don't want to load it at load time with the rest.
I am searching for the ideal method to load audio at run time, (after a checkbox has been checked, this can be after 20 minutes after opening the app) given a list of audio elements.
The list is already in a variable allSounds. I have the following audio in a webpage (there are more):
<audio preload="none">
<source src="sound1.mp3">
</audio>
I want to keep the same HTML because after second visit I can easily change it to (this works fine with my server-side HTML generation)
<audio preload="auto">
<source src="sound1.mp3">
</audio>
and it works.
Once the option is turned on, I want to load the sounds, but not play them immediately. I know that .play() loads the sounds. But I want to avoid the delay between pressing a button and the associated feedback sound.
It is better to not play sound than delayed (in my app).
I made this event handler to load sounds (it works) but in the chrome console, it says that download was cancelled, and then restarted I don't know exactly what I am doing wrong.
Is this is the correct way to force load sounds? What are the other ways? If possible without changing the HTML.
let loadSounds = function () {
allSounds.forEach(function (sound) {
sound.preload = "auto";
sound.load();
});
loadSounds = function () {}; // Execute once
};
here is playSound function, but not very important for the questions
const playSound = function (sound) {
// PS
/* only plays ready sound to avoid delays between fetching*/
if (!soundEnabled)) {
return;
}
if (sound.readyState < sound.HAVE_ENOUGH_DATA) {
return;
}
sound.play();
};
Side question: Should there be a preload="full" in the HTML spec?
See also:
Preload mp3 file in queue to avoid any delay in playing the next file in queue
how we can Play Audio with text highlight word by word in angularjs
To cache the audio will need to Base64 encode your MP3 files, and start the Base64 encoded MP3 file with data:audio/mpeg;base64,
Then you can pre-load/cache the file with css using something like:
body::after {
content:url(myfile.mp3);
display:none;
}
I think I would just use the preloading functionality without involving audio tag at all...
Example:
var link = document.createElement('link')
link.rel = 'preload'
link.href = 'sound1.mp3'
link.as = 'audio'
link.onload = function() {
// Done loading the mp3
}
document.head.appendChild(link)
I'm quite sure that I've found a solution for you. As far as I'm concerned, your sounds are additional functionality, and are not required for everybody. In that case I would propose to load the sounds using pure javascript, after user has clicked unmute button.
A simple sketch of solution is:
window.addEventListener('load', function(event) {
var audioloaded = false;
var audioobject = null;
// Load audio on first click
document.getElementById('unmute').addEventListener('click', function(event) {
if (!audioloaded) { // Load audio on first click
audioobject = document.createElement("audio");
audioobject.preload = "auto"; // Load now!!!
var source = document.createElement("source");
source.src = "sound1.mp3"; // Append src
audioobject.appendChild(source);
audioobject.load(); // Just for sure, old browsers fallback
audioloaded = true; // Globally remember that audio is loaded
}
// Other mute / unmute stuff here that you already got... ;)
});
// Play sound on click
document.getElementById('playsound').addEventListener('click', function(event) {
audioobject.play();
});
});
Of course, button should have id="unmute", and for simplicity, body id="body" and play sound button id="playsound. You can modify that of course to suit your needs. After that, when someone will click unmute, audio object will be generated and dynamically loaded.
I didn't try this solution so there may be some little mistakes (I hope not!). But I hope this will get you an idea (sketch) how this can be acomplished using pure javascript.
Don't be afraid that this is pure javascript, without html. This is additional functionality, and javascript is the best way to implement it.
You can use a Blob URL representation of the file
let urls = [
"https://upload.wikimedia.org/wikipedia/commons/b/be/Hidden_Tribe_-_Didgeridoo_1_Live.ogg"
, "https://upload.wikimedia.org/wikipedia/commons/6/6e/Micronesia_National_Anthem.ogg"
];
let audioNodes, mediaBlobs, blobUrls;
const request = url => fetch(url).then(response => response.blob())
.catch(err => {throw err});
const handleResponse = response => {
mediaBlobs = response;
blobUrls = mediaBlobs.map(blob => URL.createObjectURL(blob));
audioNodes = blobUrls.map(blobURL => new Audio(blobURL));
}
const handleMediaSelection = () => {
const select = document.createElement("select");
document.body.appendChild(select);
const label = new Option("Select audio to play");
select.appendChild(label);
select.onchange = () => {
audioNodes.forEach(audio => {
audio.pause();
audio.currentTime = 0;
});
audioNodes[select.value].play();
}
select.onclick = () => {
const media = audioNodes.find(audio => audio.currentTime > 0);
if (media) {
media.pause();
media.currentTime = 0;
select.selectedIndex = 0;
}
}
mediaBlobs.forEach((blob, index) => {
let option = new Option(
new URL(urls[index]).pathname.split("/").pop()
, index
);
option.onclick = () => console.log()
select.appendChild(option);
})
}
const handleError = err => {
console.error(err);
}
Promise.all(urls.map(request))
.then(handleResponse)
.then(handleMediaSelection)
.catch(handleError);

audio auto play next song when previous is finished

I want to create an audio background player where user can only click on image to play or stop the playback. I have trouble creating or rewirting existing codes to make a playlist for it, that automatically plays next song when previous is finished. I want to do it in vanilla js.
Here is what I have so far:
https://jsfiddle.net/rockarou/ad8Lkkrj/
var imageTracker = 'playImage';
swapImage = function() {
var image = document.getElementById('swapImage');
if (imageTracker == 'playImage') {
image.src = 'http://findicons.com/files/icons/129/soft_scraps/256/button_pause_01.png';
imageTracker = 'stopImage';
} else {
image.src = 'http://findicons.com/files/icons/129/soft_scraps/256/button_play_01.png';
imageTracker = 'playImage';
}
};
var musicTracker = 'noMusic';
audioStatus = function() {
var music = document.getElementById('natureSounds');
if (musicTracker == 'noMusic') {
music.play();
musicTracker = 'playMusic';
} else {
music.pause();
musicTracker = 'noMusic';
}
};
here is the trick to trigger next song:
music.addEventListener('ended',function(){
//play next song
});
How to play another song on same audio tag:
music.pause();
music.src = "new url";
music.load();
music.play();
Now here is a cool example of a playlist in html5, you can load each song at the time, case some clients (mobile) will not be happy when you consume the traffic, in next example all audios are loaded at same time to have a smooth transition from song to song,
loading the songs:
//playing flag
var musicTracker = 'noMusic';
//playlist audios
var audios = [];
$(".song").each(function(){
var load = new Audio($(this).attr("url"));
load.load();
load.addEventListener('ended',function(){
forward();
});
audios.push(load);
});
//active track
var activeTrack = 0;
Highlighting witch song is playing, with a bit of jquery, yeah, case yeah I'm lazy, lazy:
var showPlaying = function()
{
var src = audios[activeTrack].src;
$(".song").removeClass("playing");
$("div[url='" + src + "']").addClass("playing");
};
Fiddle here
Note: If the sound's doesn't play, manually check if audio url's are accessible
[Here a non vanilla solution.] My playlist consists of four songs, they are named 0.mp3, 1.mp3, 2.mp3 and 3.mp3.
<html>
<head><script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script></head>
<body>
<audio id="player" autoplay controls><source src="0.mp3" type="audio/mp3"></audio>
</body>
<script>
var x = 0;
var music = document.getElementById("player");
$("#player").bind("ended", function(){
x=x+1;
music.src = x%4 + ".mp3";
music.load();
music.play();
});
</script>
</html>
The playlist is repeated indefinetely.
Vanilla Javascript variant:
const audioArray = document.getElementsByClassName('songs'); //Get a list of all songs
let i = 0; //Initiate current Index
const player = document.getElementById('player'); //get the player
player.src = audioArray[i].getAttribute('data-url'); //set first Song to play
player.addEventListener('ended',function(){ //when a song finished playing
i++; //increase index
if (i < audioArray.length) { //If current index is smaller than count of songs
player.src = audioArray[i].getAttribute('data-url'); //set next song
return; // stop further processing of this function for now
}
// current index is greater than count of songs
i = 0; // therefore we reset the current index to the first available song
player.src = audioArray[i].getAttribute('data-url'); // and set it to be played
});
In this example you don't set an initial src for the audioplayers source-tag but instead have a list of class 'song'-items with an data-url attribute containing the url/path to the tracks.
I added comments to learn what and why this code is doing what it does.
Of course it could be better but it's a quick throwup of code ;)

Categories