I have an audio file and a javascript for it.
The javascript displays percentage of the audio buffered, if no buffered occurs it displays loading...
function loop2() {
var audio2 = document.getElementById("atwo1");
var percentages = document.getElementsByClassName("atwo1l")
var buffered = audio2.buffered;
var loaded;
if (buffered.length) {
loaded = 100 * buffered.end(0) / audio2.duration;
if (loaded.toFixed(2) != '0') {
percentages[0].innerHTML = 'Loading: ' + loaded.toFixed(2) + '%';
} else {
percentages[0].innerHTML = 'Loading....';
}
}
setTimeout(loop2, 50);
}
loop2();
<audio id="atwo1" controls="controls">
<source src="https://docs.google.com/uc?export=download&id=19gLpR7J8TVHmooVbM23eK5Xq0f9YXNZf">
</audio>
<p><span class="atwo1l"></span></p>
But for the above code, it does not displays loading...
When we place small audio file it will display. So why not for large files?
Update:
Found a partial answer (updated codes)
Why a partial answer?
All comments together in an answer
function loop2() {
var audio2 = document.getElementById("aone1"),
percentages = document.getElementsByClassName("aone1l"),
buffered,
loaded;
if (audio2 && percentages) { // if both elements are found in the DOM
buffered = audio2.buffered;
if (buffered.length) {
loaded = 100 * buffered.end(0) / audio2.duration;
if (loaded.toFixed(2) != '0') {
percentages[0].innerHTML = 'Loading: ' + loaded.toFixed(2) + '%';
}
if(loaded >= 1){
audio2.classList.remove('un-buffered');
}
} else { // handle the case where the buffered.length is 0 or undefined
percentages[0].innerHTML = 'Loading....';
}
}
setTimeout(loop2, 50);
}
Related
I want to use a custom audio player to play sound tracks hosted online.
For example I want to be able to feed the audio player a link like
example.com/path/to/track.mp3
and it should parse it and play it. I can play sound tracks hosted locally
Here is the code where I have the problem. I have an audio object that points to a local folder where the sound tracks are. I am not sure how to deal with this when it is not hosted locally.
When I replace the path with the URL the audio player just freezes.
$(function () {
var count = 0;
var audio;
//Hide Pause
$('#pause').hide();
initAudio($('#playlist li:first-child'));
function initAudio(element) {
var song = element.attr('song');
var cover = element.attr('cover');
var artist = element.attr('artist');
var title = element.text();
var temp = parseFloat($('#volume-slider').val() / 100);
//Create audio object
audio = new Audio('../media/books/' + song);
audio.volume = temp;
audio.addEventListener("loadedmetadata", function () {
minutes = parseInt(audio.duration / 60);
seconds = parseInt(audio.duration % 60);
if (seconds < 10) {
seconds = '0' + seconds;
};
if (minutes < 10) {
minutes = '0' + minutes;
};
$('#duration').html(minutes + ':' + seconds);
});
$("#auto-play").click(function () {
if (count === 1) {
$("#auto-play").css("background-color", "black");
count = 0;
} else {
$("#auto-play").css("background-color", "rgb(0,0,255)");
count = 1;
}
});
audio.addEventListener('ended', function () {
if (count > 0) {
var next = $('#playlist li.active').next();
if (next.length == 0) {
next = $('#playlist li:first-child');
}
initAudio($(next));
audio.play();
showCurrentTime();
}
});
//Inserts track info
$('.artist').text(artist);
$('.title').text(title);
$('#duration').text();
//Insert song cover. NOTE: the path below is relative to the
//html "img.cover" element not this js file.
$('img.cover').attr('src', '../media/books/covers/' + cover);
$('#playlist li').removeClass('active');
element.addClass('active');
};
});
You can avoid CORS errors with something like this.
For your local development it would be easy.
If you would like to go in production, it would be bit harder. The Server with the soundtracks has to accept your App.
I should start by saying I'm not good with JS and I'm still trying to learn it.
I have 10 mp4s and I need to play one at random on a button click. I'm having trouble making it happen and I've searched around for a solution but to no avail.
Here's what I have so far:
HTML
<div class="videoHolder">
<video id="video" autoplay muted>
Your browser does not support the video tag.
</video>
</div>
<button type="button" name="button">Push to Play</button>
JS
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4",
];
var videoId = 0;
var elemVideo = document.getElementById('video');
var elemSource = document.createElement('source');
elemVideo.appendChild(elemSource);
elemVideo.addEventListener('ended', play_next, false);
function play_next() {
if (videoId == 10) {
elemVideo.stop();
} else {
video.pause();
elemSource.setAttribute('src', videos[videoId]);
videoId++;
elemVideo.load();
elemVideo.play();
}
}
play_next();
</script>
This unfortunately doesn't do what I need. This code will play all 10 videos one after the other on page load, then stop. I need it to only play one of the random 10 videos when someone pushes the "Push to Play" button. And I need it to keep going after 10.
Like I said I'm not good with JS at all and I was able to find this code from browsing around and modifying it a bit.
This should work for you.
<div class="videoHolder">
<video id="video" autoplay muted src="">
</video>
</div>
<button id='playRandom' type="button" name="button">Push to Play</button>
This is a really basic implementation of what you want
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4"
];
var videoId = getRandomInt(0, 9);
var elemVideo = document.getElementById('video');
elemVideo.setAttribute('src', '/' + videos[videoId]);
var btn = document.getElementById('playRandom');
btn.addEventListener('click', function (e) {
var nextId = getRandomInt(0, 9);
if (nextId != videoId) {
playNext(nextId);
} else {
while (nextId == videoId) {
nextId = getRandomInt(0, 9);
}
playNext(nextId);
}
});
/* gets random whole number between 0 and 9 */
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function playNext(id) {
elemVideo.setAttribute('src', '/' + videos[id]);
elemVideo.play();
}
This is a more robust implementation that includes a history of previously played videos so you don't play the same videos over again.
var videos = [
"mp4s/video1.mp4",
"mp4s/video2.mp4",
"mp4s/video3.mp4",
"mp4s/video4.mp4",
"mp4s/video5.mp4",
"mp4s/video6.mp4",
"mp4s/video7.mp4",
"mp4s/video8.mp4",
"mp4s/video9.mp4",
"mp4s/video10.mp4"
];
var playedVideos = [];
var videoId = getRandomInt(0, 9);
var elemVideo = document.getElementById('video');
elemVideo.setAttribute('src', '/' + videos[videoId]);
var btn = document.getElementById('playRandom');
btn.addEventListener('click', playRandom);
function playRandom(e) {
var nextId = getRandomInt(0, 9);
if (nextId != videoId) {
if (!playNext(nextId)) {
playRandom(e);
}
} else {
while (nextId == videoId) {
nextId = getRandomInt(0, 9);
}
if (!playNext(nextId)) {
playRandom(e);
}
}
}
/* gets random whole number between 0 and 9 */
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function playNext(id) {
// checks if the video has already been played
for (var src in playedVideos) {
if (src == videos[id]) {
return false;
}
}
elemVideo.setAttribute('src', '/' + videos[id]);
elemVideo.play();
// adds src to arr of played videos
playedVideos.push(videos[id]);
/*
* Everything from here on is optional depending on whether you want to
* - iterate over the arr of videos and play each videos at least once before starting over or
* - you want to stop playing videos after playing each at least once
*/
// empties the played videos arr and allows you to start playing a new set of random videos
if (playedVideos.length() == 10) {
playedVideos = [];
// if you'd like to stop playing videos altogether at this, point delete the previous statement and display a prompt saying the playlist is over
// or if you'd like to reset the playlist, then remove the event listener ('playRandom') and display a reset button that starts everything over from the beginning.
}
return true;
}
I want to use a video tag and control it with javascript,
but it doesn't work as I want.
function vidplay(evt) {
if (video.src == "") { // inital source load
getVideo();
}
button = evt.target; // get the button id to swap the text based on the state
if (video.paused) { // play the file, and display pause symbol
video.play();
button.textContent = "||";
} else { // pause the file, and display play symbol
video.pause();
button.textContent = ">";
}
}
// load video file from input field
function getVideo() {
var d = document.getElementById('a4').innerHTML; // video file name
// var fileURL = document.getElementById("videoFile").value; // get input field
var fileURL = d; // get input field
if (fileURL != "") {
video.src = fileURL;
video.load(); // if HTML source element is used
document.getElementById("play").click(); // start play
} else {
errMessage("Enter a valid video URL"); // fail silently
}
}
var d in function getVideo() is like "http://192.168.44.112/~/~.mp4"
This video was uploaded on mongoDB and I want to use it.
The video works well but the seek bar doesn't work at all,
it only seeks to time 0.
document.getElementById("rew").addEventListener("click", function() {
setTime(-10);
}, false);
document.getElementById("fwd").addEventListener("click", function() {
setTime(10);
}, false);
function setTime(tValue) {
// if no video is loaded, this throws an exception
try {
if (tValue == 0) {
video.currentTime = tValue;
} else {
video.currentTime += tValue;
}
} catch (err) {
// errMessage(err) // show exception
errMessage("Video content might not be loaded");
}
}
And when i use setTime() function, it goes to seek time 0, while I want to seek at the time corresponding to where I click .
How can I do it ?
I made this quick example that you can test & study, then afterwards you can just apply a similar logic to your above shown code. Hope it helps your problem.
<video id="myVid" width="640" height="480" controls>
<source src="yourVideoFile.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<script>
tValue = 0; //start at zero
myVid.addEventListener('seeking', function(e){ tValue = myVid.currentTime })
function setTime_FWD()
{
try
{
if (tValue >= myVid.duration) { tValue = myVid.duration; }
else { tValue += 10; myVid.currentTime = tValue; }
}
catch (err) { errMessage("Video content might not be loaded"); }
}
function setTime_RWD()
{
try
{
tValue -= 10;
if (tValue <= 0) { myVid.currentTime = tValue = 0; }
else { myVid.currentTime = tValue; }
}
catch (err) { errMessage("Video content might not be loaded"); }
}
</script>
<br><br>
<button onclick="setTime_RWD()"> << </button>
<button onclick="setTime_FWD()"> >> </button>
I found a custom html5 audio player and successfully redesigned it, now I want to add a "loading/buffering" text while player is loading audio (otherwise users may freak out because nothing happening after they hit play).
Here is the code to explain:
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.substr(0, 2),
time = minutes + ':' + seconds
return time;
}
function calculateCurrentValue(currentTime) {
var current_hour = parseInt(currentTime / 3600) % 24,
current_minute = parseInt(currentTime / 60) % 60,
current_seconds_long = currentTime % 60,
current_seconds = current_seconds_long.toFixed(),
current_time = (current_minute < 10 ? "0" + current_minute : current_minute) + ":" + (current_seconds < 10 ? "0" + current_seconds : current_seconds);
return current_time;
}
function initProgressBar() {
var player = document.getElementById('player');
var length = player.duration
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length)
jQuery(".end-time").html(totalLength);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
jQuery(".start-time").html(currentTime);
var progressbar = document.getElementById('seekObj');
progressbar.value = (player.currentTime / player.duration);
progressbar.addEventListener("click", seek);
if (player.currentTime == player.duration) {
$('#play-btn').removeClass('pause');
}
function seek(evt) {
var percent = evt.offsetX / this.offsetWidth;
player.currentTime = percent * player.duration;
progressbar.value = percent / 100;
}
};
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById('player-container'),
player = document.getElementById('player'),
isPlaying = false,
playBtn = document.getElementById('play-btn');
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener('click', function() {
togglePlay()
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$('#play-btn').removeClass('pause');
} else {
player.play();
$('#play-btn').addClass('pause');
isPlaying = true;
}
}
}());
}
}
initPlayers(jQuery('#player-container').length);
Player code (source) on CodePen
I want some text will be shown in the same "span" that shows
"start time" (please see CodePen) while media is loading;
The text " 'loading.' 'loading..' 'loading...' " must changing on
loop while media is loading;
When it is loaded the "loading" text must be changing on "start
time" as it is now.
So basically I wat to put some text in start time while it is not shows anything but zeroes
I'm new to JS
Thats why I need some help or point to right direction
You can use the "readyState" event of the audio player to show hide loading.
There is already a "SetInterval" even which is getting fired so in that we can add this code to show/hide the "Loading"
1st add the loading element(You can put it where ever you want"
<h3 id="loading" style="display:none;">Loading</h3>
Now let's add the code to check "readystate" inside "SetInterval"
if(player.readyState>0&&player.readyState<4){
$("#loading").show();
}
else{
$("#loading").hide();
}
You can read more about "readystate" here
/As per the request I have changed the code to use the start time as loading, to make it work we don't have to add anything inside html but need to do some changes in JS
First, add this inside "togglePlay" functions pay condition in the "else" block.
$(".start-time").html("Loading...");
After this inside "initProgressBar()" function replace the "jQuery(".start-time").html(currentTime);" with the below code
if (player.readyState === 4) {
jQuery(".start-time").html(currentTime);
}
so how it will work, When you click play button the start time text will show as "Loading" but once the file is loaded and the player is ready to play the text will be changed to "start time", Hope it works. Also updated the CodePen for better understanding
You can find the full code in the CodePen
You could use setInterval to cycle through the different 'loading' text and clearInterval when the player's play promise is done.
Here's a basic example:
var dots = 1;
var loading = setInterval(function(){
dots = (dots % 3) + 1;
$(".start-time").text("Loading" + Array(dots + 1).join("."));
console.log($(".start-time").text());
}, 250);
player.play().then(function() {
clearInterval(loading);
}).catch((error) => {
$(".start-time").text("Error loading");
});
The Audio player loads and initializes, but the controls disappear once I pass the third song (see >= 3 test). I'm not certain if that's an incredible coincidence but it seems likely I have broken something. Why do the audio controls vanish?
Also, the volume controls do not initialize. Does anyone know why?
<script>
window.onload = function() {
var number = Math.floor((Math.random() * 10) + 1);
if(number >= 3) {
document.getElementById("audio").innerHTML = "<audio id='vid' src='remix.mp3' type='audio/mpeg' autoplay='true' loop='true'></audio>";
} else {
document.getElementById("audio").innerHTML = "<audio id='vid' src='lose.mp3' type='audio/mpeg' autoplay='true' loop='true'></audio>";
}
};
(function(){
var vid = document.getElementById("vid");
vid.volume = 0.2;
});
</script>
<script>
jQuery(function($) {
$("#vid").prop('volume', 0.2);
window.setVolume = function(bgAudio,vol) {
sounds[bgAudio].volume = 0.33;
}
});
</script>
<div id="audio">
</div>
There is no need to replace the whole audio tag. Just change the src attribute:
<audio id='vid' src='remix.mp3' type='audio/mpeg' autoplay='true' loop='true'></audio>
...
$('#vid').attr('src', 'remix.mp3');
EDIT
Your code is a mess, I've tried to refactor it a bit:
(function() {
var number = Math.floor((Math.random() * 10) + 1);
var player = $('#vid');
player.attr('src', number >= 3 ? 'remix.mp3' : 'lose.mp3');
player.prop('volume', '0.2');
player[0].play(); //run the audio track
//not sure about this function
window.setVolume = function(bgAudio, vol) {
sounds[bgAudio].volume = vol;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<audio id='vid' src='' type='audio/mpeg' loop='true'></audio>
And check mp3 file names and location.