Custom html 5 player multiple tracks does not work - javascript

I am trying to create multiple custom javascript audio players on my website but once I copy the code in html the second player does not work, how should I adjust the javascript code for it to work? Here is my code: https://github.com/streamofstream/streamofstream.github.io
and here is relevant part of the code that I am talking about:
index.html relevant part here, I tried to just duplicate this part and change the audio source but once I do this the second player appears but it wont trigger javascript
<script>
function durationchange() {
var duration = $('audio')[0].duration;
if(!isNaN(duration)) {
$('#duration').html(Math.ceil(duration));
}
}
</script>
<div id="audioWrapper">
<audio id="audioPlayer" preload="metadata">
<source src="assets/millriver.wav" type="audio/wav" />
Your browser does not support the audio element.
</audio>
<div id="playPause" class="play"></div>
<div id="trackArtwork"><img src="assets/smiths.jpg" /></div>
<div id="trackArtist">04/28/2021, 8PM Eastern Time, Mill River</div>
<div id="trackTitle">41°20'09.3"N 72°54'37.7"W</div>
<div id="trackProgress">
<div id="elapsedTime"></div>
<input type="range" id="scrubBar" value="0" max="100" />
<div id="remainingTime"></div>
</div>
</div>
<script type="text/javascript" src="js/audioplayer.js"></script>
and java script here (Code by https://github.com/jon-dean/html5-audio-player)
var audioPlayer = document.getElementById('audioPlayer');
var scrubBar = document.getElementById('scrubBar');
var elapsedTime = document.getElementById('elapsedTime');
var remainingTime = document.getElementById('remainingTime');
var playPause = document.getElementById('playPause');
var trackLength;
// Set up a listener so we can get the track data once it's loaded
audioPlayer.addEventListener('loadedmetadata', function() {
// Get the length for the current track
trackLength = Math.round(audioPlayer.duration);
// Set the initial elapsed and remaining times for the track
elapsedTime.innerHTML = formatTrackTime(audioPlayer.currentTime);
remainingTime.innerHTML = '-' + formatTrackTime(trackLength - audioPlayer.currentTime);
});
function runWhenLoaded() { /* read duration etc, this = audio element */ }
// Set up a listener to watch for play / pause and display the correct image
playPause.addEventListener('click', function() {
// Let's check to see if we're already playing
if (audioPlayer.paused) {
// Start playing and switch the class to show the pause button
audioPlayer.play();
playPause.className = 'pause';
} else {
// Pause playing and switch the class to show the play button
audioPlayer.pause();
playPause.className = 'play';
}
});
// Track the elapsed time for the playing audio
audioPlayer.ontimeupdate = function() {
// Update the scrub bar with the elapsed time
scrubBar.value = Math.floor((100 / trackLength) * audioPlayer.currentTime);
// Update the elapsed and remaining time elements
elapsedTime.innerHTML = formatTrackTime(audioPlayer.currentTime);
remainingTime.innerHTML = '-' + formatTrackTime(trackLength - audioPlayer.currentTime + 1);
};
// Set up some listeners for when the user changes the scrub bar time
// by dragging the slider or clicking in the scrub bar progress area
scrubBar.addEventListener('input', function() {
changeTrackCurrentTime();
scrubBar.addEventListener('change', changeTrackCurrentTime);
});
scrubBar.addEventListener('change', function() {
changeTrackCurrentTime();
scrubBar.removeEventListener('input', changeTrackCurrentTime);
});
// Change the track's current time to match the user's selected time
var changeTrackCurrentTime = function() {
audioPlayer.currentTime = Math.floor((scrubBar.value / 100) * trackLength);
};
// Format the time so it shows nicely to the user
function formatTrackTime(timeToFormat) {
var minutes = Math.floor((timeToFormat) / 60);
var seconds = Math.floor(timeToFormat % 60);
seconds = (seconds >= 10) ? seconds : '0' + seconds;
return minutes + ':' + seconds;
}
// Let's reset everything once the track has ended
audioPlayer.addEventListener('ended', function() {
audioPlayer.currentTime = 0;
elapsedTime.innerHTML = formatTrackTime(audioPlayer.currentTime);
remainingTime.innerHTML = '-' + formatTrackTime(trackLength - audioPlayer.currentTime);
playPause.className = 'play';
});
Thank you

Related

How to get duration from audio tag in react? [duplicate]

I have a html5 <audio> tag in page, but how can I know its duration time?
<audio controls="">
<source src="p4.2.mp3">
</audio>
2020 solution:
You will get undefined or NaN (not a number) when the audio metadata isn't loaded yet. Therefore some people suggested to use onloadedmetadata to make sure the metadata of the audio file is fetched first. Also, what most people didn't mention is that you have to target the first index of the audio DOM element with [0] like this:
-- Vanilla Javascript:
var audio = document.getElementById('audio-1');
audio.onloadedmetadata = function() {
alert(audio.duration);
};
If this won't work try this, however not so reliable and dependent on users connection:
setTimeout(function () {
var audio = document.getElementById('audio-1');
console.log("audio", audio.duration);
}, 100);
-- JQuery:
$(document).ready(function() {
var audio = $("#audio-1")[0];
$("#audio-1").on("loadedmetadata", function() {
alert(audio.duration);
});
});
var au = document.createElement('audio');
au.addEventListener('loadedmetadata',function(){
au.setAttribute('data-time',au.duration);
},false);
In a comment above, it was mentioned that the solution is to bind an event handle to the event loadedmetadata. This is how I did that -
audio.onloadedmetadata = function() {
alert(audio.duration);
};
I was struggling with loading the duration in a React component so following #AlexioVay's solution, here is an answer if you're using React:
This assumes you are using a ref for your audio component class which you will need to target the audio elements for your play/pause handler(s).
<audio /> element:
<audio ref={audio => { this.audio = audio }} src={this.props.src} preload="auto" />
Then in your componentDidMount():
componentDidMount() {
const audio = this.audio
audio.onloadedmetadata = () => {
console.log(audio.duration)
this.setState({
duration: this.formatTime(audio.duration.toFixed(0))
})
}
}
And finally the formatTime() function:
formatTime(seconds) {
const h = Math.floor(seconds / 3600)
const m = Math.floor((seconds % 3600) / 60)
const s = seconds % 60
return [h, m > 9 ? m : h ? '0' + m : m || '0', s > 9 ? s : '0' + s]
.filter(a => a)
.join(':')
}
With this, the duration in h:mm:ss format will display as soon as the audio src data is loaded. Sweetness.
I used "canplaythrough" event to get the track duration. I have a case where I have two players, and I want to stop the second player 2 seconds before the first one is complete.
$('#' + _currentPlayerID).on("canplaythrough", function (e) {
var seconds = e.currentTarget.duration;
var trackmills = seconds * 1000;
var subTimeout = trackmills - 2000; //2 seconds before end
//console.log('seconds ' + seconds);
//console.log('trackmills ' + trackmills);
//console.log('subTimeout ' + subTimeout);
//Stop playing before the end of thet track
//clear this event in the Pause Event
_player2TimeoutEvent = setTimeout(function () { pausePlayer2(); }, subTimeout);
});
Simply use audioElement.duration
To obtain the end of reading it is necessary that 'loop = false' with the event 'onended'. If loop = true, onended does not work;)
To make a playlist, you have to set loop = false to use the 'onended' event in order to play the next song.
for the duration if your script is done correctly you can recover the duration anywhere. If the value of 'duration' is NaN the file is not found by the browser. If the value is 'Infinity' 'INF' it is a streaming, in this case, adds 1 mn compared to the reading time 'currentime'.
For * I.E it's crap. Currenttime may be greater than duration, in which case you do:
var duration = (this.currentime> this.duration)? this.currenttime: this.duration;
That's (O_ °)
it's better to use the event like this ...
ObjectAudio.onprogress =function(){
if(this.buffered.length){
var itimeend = (this.buffered.length>1)? this.buffered.end(this.buffered.length-1):this.buffered.end(0);
....
Your code here.......
}
}

How to add audio to a 10 second countdown in javascript

First time posting on here so go easy.
I am having some problems with a recent project. I am trying to create a countdown as the landing page with audio sounds for each number (street fighter 2 sound effects if anyone is familiar). I have managed to get the countdown to work and it will work but only at the click of a button as this is the only way I could get it to work.
Like I said this is not the desired effect as once the countdown finishes I want it to load the main page. Also in regards to adding the sound to each individual number, I have absolutely no idea where to start!
This is my current JS for it
document.addEventListener('DOMContentLoaded', () => {
const timeLeftDisplay = document.querySelector('#time-left')
const startBtn = document.querySelector('#start-button')
let timeLeft = 10
function countDown (){
setInterval(function(){
if(timeLeft <= 0){
clearInterval(timeLeft = 0)
}
timeLeftDisplay.innerHTML = timeLeft
timeLeft -= 1
}, 1000)
}
startBtn.addEventListener('click', countDown)
} )
This is the current HTML
<script type= "text/javascript" src="assets/javascript/script.js"></script>
<title>Bro-nament</title>
</head>
<body>
<div class="container text-center">
<h1 class="bro-title"> TIME TILL BRO - DOWN</h1>
<h2 id="time-left"> 10 </h2>
<button id="start-button"> <i class="fas fa-fist-raised"> Continue? </i> <i class="fas fa-fist-raised"></i></button>
Current page view
Thanks
In your server, you need to name your audio files with a number for all of them and use the value of time variable to increment and get the url of the file for each every seconde.
Like :
9.mp3
8.mp3
7.mp3
6.mp3
....
Once the counter is to 0, you redirect where the url you want.
let time = 10;
countdown();
function countdown() {
// we upadate number text
document.querySelector('#time-left').textContent = --time;
// if count is equal to 0 (end of counter)
if (time === 0) {
time = 10;
// we redirect to this url
window.location.href = "http://www.google.com";
// we stop the loop
return false;
}
//console.log(time);
// we set the url of audio file for each seconde
const audio = new Audio("https://srv-store5.gofile.io/download/RFgvcw/" + time + ".mp3");
// if you only want one, u dont need the const time
//const audio = new Audio("https://srv-store5.gofile.io/download/RFgvcw/1.mp3");
audio.play();
setTimeout(countdown, 1000);
}
#time-left {
font-size: 150px;
font-weight: bold;
margin: auto 0;
text-align: center;
}
<div id="time-left"></div>

can html5 audio streaming be 100 % sync with current device time

I wanted to know if it is possible HTML5 audio streaming super accurately synced with device current time.
like I have a 10 minutes of audio file at device time 01:00 audio starts from 00:00 and at 01:05 audio plays at 05:00 and end at 01:10. I mean when ever I click play HTML5 audio player it play the audio according to the current device time.
Here is what I tried but audio is always a little behind the time (in milliseconds).
var player = document.getElementById('music');
player.addEventListener('play', function() {
var main_date = new Date();
var hour = main_date.getUTCHours();
var minutes = main_date.getUTCMinutes();
var seconds = main_date.getUTCSeconds();
var current_second = ( hour * 60 * 60 ) + ( minutes * 60 ) + seconds;
var audio_start = current_second%player.duration ;
player.currentTime = parseInt(audio_start);
}, false);
player.addEventListener('timeupdate', updateProgressBar, false);
function updateProgressBar() {
var percentage = Math.floor((100 / player.duration) * player.currentTime);
var di = document.getElementById('datetime');
di.innerHTML = new Date() ;
}
<div id="datetime"></div>
<audio controls id="music">
<source src="http://www.easel.ca/wp-content/uploads/2018/03/ClAudioSync-599_99seconds_128kbps.mp3">
<audio>
Your best bet is to use Web Audio API.
By using WAA you would typically first load the entire sample into memory, then use the currentTime on the AudioContext to schedule the sample. Use the offset argument to determine start point in the sample.

Chrome extension simulate hover over Youtube player

I am developing a Chrome extension for Youtube and when the user clicks a button that I have created I want to simulate a mouse hover over the player, without moving the mouse. When a video is playing and the mouse is, manually, hovered over the player, the controls (play, pause etc) and the progress bar shows and this is what I am trying to accomplish, but with a button click instead of hovering.
I don't want to pause the video, only show the bottom controls and progress bar when the user clicks the button I have created.
manifest.json
//name, description, background etc
"content_scripts": [
{
"matches": ["http://www.youtube.com/*", "https://www.youtube.com/*"],
"js": ["jquery.js", "content.js"]
}
]
content.js
$('#myButton').on('click', function() {
//I have tried the following:
$('#movie_player').trigger('mouseenter')
$('#movie_player').mouseenter()
document.getElementById('movie_player').onmouseenter()
//I can play/pause the video with:
$('#movie_player').click()
}
I have also tried "mouseover" (jQuery) and "onmouseover" (javascript) and I have also tried these on several different child elements of the #movie_player without success.
When hovering manually over the player, Chrome's DevTools shows me that the #movie_player element has a class (ytp-autohide) which gets removed/added when the mouse is entering/leaving the element. However. I can't just remove this class when the user clicks my button because then the progress bar/duration time is not updated.
Any ideas?
Managed to solve it if someone is interested (with help from this extension)
$('#myButton').on('click', function() {
const ytplayer = document.querySelector('.html5-video-player')
const video = ytplayer.querySelector('video')
const progressbar = ytplayer.querySelector('.ytp-play-progress')
const loadbar = ytplayer.querySelector('.ytp-load-progress')
//show controls and progress bar
$('.html5-video-player').toggleClass('ytp-autohide')
//update red progress bar
video.addEventListener('timeupdate', updateProgressBar)
function updateProgressBar() {
progressbar.style.transform = 'scaleX('+(video.currentTime/video.duration)+')'
}
//update grey buffer progress
video.addEventListener('progress', updateBufferProgress)
function updateBufferProgress() {
loadbar.style.transform = 'scaleX('+(video.buffered.end(video.buffered.length-1)/video.duration)+')'
}
//update current time
$('.ytp-time-current').text(formatTime( video.currentTime ))
//update current time every second
const i = setInterval(function(){
$('.ytp-time-current').text(formatTime( video.currentTime ))
}, 1000)
//stop after 3 seconds
setTimeout(function() {
$('.html5-video-player').toggleClass('ytp-autohide')
clearInterval(i)
video.removeEventListener('timeupdate', updateProgressBar)
video.removeEventListener('progress', updateBufferProgress)
}, 3000)
}
function formatTime(time){
time = Math.round(time)
const minutes = Math.floor(time / 60)
let seconds = time - minutes * 60
seconds = seconds < 10 ? '0' + seconds : seconds
return minutes + ':' + seconds
}

Custom progress bar for <audio> and <progress> HTML5 elements

I am mind boggled at working out how to create a custom seekbar for an audio player using the tag and simple Javascript.
Current Code:
<script>
function play() {
document.getElementById('player').play();
}
function pause() {
document.getElementById('player').pause();
}
</script>
<audio src="sample.mp3" id="player"></audio>
<button onClick="javascript:play()" >Play</button>
<button onClick="javascript:pause()" >Pause</button>
<progress id="seekbar"></progress>
Would it be possible to link the progress bar so that when i play a song the progress is shown?
Yes, it is possible using the timeupdate event of the audio tag. You receive this event every time the position of the playback is updated. Then, you can update your progress bar using the currentTime and duration properties of the audio element.
You can see a working example in this fiddle
If you want smooth progress bar,try somethink like that
HTML:
<div class="hp_slide">
<div class="hp_range"></div>
</div>
CSS:
.hp_slide{
width:100%;
background:white;
height:25px;
}
.hp_range{
width:0;
background:black;
height:25px;
}
JS:
var player = document.getElementById('player');
player.addEventListener("timeupdate", function() {
var currentTime = player.currentTime;
var duration = player.duration;
$('.hp_range').stop(true,true).animate({'width':(currentTime +.25)/duration*100+'%'},250,'linear');
});
Pretty rough,but works
Here's a simple vanilla example:
const url = "https://upload.wikimedia.org/wikipedia/en/a/a9/Webern_-_Sehr_langsam.ogg";
const audio = new Audio(url);
const playBtn = document.querySelector("button");
const progressEl = document.querySelector('input[type="range"]');
let mouseDownOnSlider = false;
audio.addEventListener("loadeddata", () => {
progressEl.value = 0;
});
audio.addEventListener("timeupdate", () => {
if (!mouseDownOnSlider) {
progressEl.value = audio.currentTime / audio.duration * 100;
}
});
audio.addEventListener("ended", () => {
playBtn.textContent = "▶️";
});
playBtn.addEventListener("click", () => {
audio.paused ? audio.play() : audio.pause();
playBtn.textContent = audio.paused ? "▶️" : "⏸️";
});
progressEl.addEventListener("change", () => {
const pct = progressEl.value / 100;
audio.currentTime = (audio.duration || 0) * pct;
});
progressEl.addEventListener("mousedown", () => {
mouseDownOnSlider = true;
});
progressEl.addEventListener("mouseup", () => {
mouseDownOnSlider = false;
});
button {
font-size: 1.5em;
}
<button>▶️</button>
<input type="range" value="0" min="0" max="100" step="1">
The approach is to use an input[type="range"] slider to reflect the progress and allow the user to seek through the track. When the range changes, set the audio.currentTime attribute, using the slider as a percent (you could also adjust the max attribute of the slider to match the audio.duration).
In the other direction, I update the slider's progress on timeupdate event firing.
One corner case is that if the user scrolls around with their mouse down on the slider, the timeupdate event will keep firing, causing the progress to hop around between wherever the user's cursor is hovering and the current audio progress. I use a boolean and the mousedown/mouseup events on the slider to prevent this from happening.
See also JavaScript - HTML5 Audio / custom player's seekbar and current time for an extension of this code that displays the time.
First of all, don't use the progress element, it's a shitty element (for now) and styling it is a huge pain in... well it's boring (look at a little project I made, look at it (and it's juste webkit/moz)).
Anyway, you should read the doc on MDN, it's very easy and with a lot of examples. What you are looking for is the currentTime attribute, here a little snippet :
var audio = document.querySelector('#player')
audio.currentTime = 60 // will go to the 60th second
So what you need is to use the cross-multiplication (div is the element you use as a progress bar) :
Where I clicked on div | THE TIME I WANT TO KNOW
————————————————————————————————————————
Total length of div | The total time of my video/audio (audio.seekable.end())

Categories

Resources