seek bar handling with javascript on HTML5 audio tag - javascript

I've my codes as below
<header>
<audio src="friends_and_family_03.mp3" id="audio" controls></audio>
<input type="range" step="any" id="seekbar"></input>
<script>
seekbar.value = 0;
var audio = document.getElementById("audio");
var seekbar = document.getElementById('seekbar');
function setupSeekbar() {
seekbar.min = audio.startTime;
seekbar.max = audio.startTime + audio.duration;
}
audio.ondurationchange = setupSeekbar;
function seekAudio() {
audio.currentTime = seekbar.value;
}
function updateUI() {
var lastBuffered = audio.buffered.end(audio.buffered.length-1);
seekbar.min = audio.startTime;
seekbar.max = lastBuffered;
seekbar.value = audio.currentTime;
}
seekbar.onchange = seekAudio;
audio.ontimeupdate = updateUI;
</script>
<p>
<button type="button" onclick="audio.play();">Play</button>
<button type="button" onclick="audio.pause();">Pause</button>
<button type="button" onclick="audio.currentTime = 0;"><< Rewind</button>
</p>
</header>
This is as explained in http://dev.opera.com/articles/view/everything-you-need-to-know-about-html5-video-and-audio/
My problems are
1) The seekbar max value is not set according to the audio duration. (The seekbar width is just around half the audio duration).
2) The seekbar doesnt show any progress as the audio plays on but if you drag the seekbar, the currenTime actually changes.
Can anyone help me modify my code so that it functions properly??

If you are caught up with the same problem, here's the solution. (I got it from another forum). Just add these two lines:
audio.addEventListener('durationchange', setupSeekbar);
audio.addEventListener('timeupdate', updateUI);
Or maybe I was just a little too stupid!! lol

Related

How to make it so not every sound plays at once when hovering over a card

I tried making character cards, that when hovered over play the character his / her voiceline (only relevant parts shown), but when I hover over a character, they play every voiceline all at once, it's probably a mistake in the javascript, but I just can't figure out how to fix it.
<ul>
<header id="play_1">
<img src="/img/characters/character.png">
<audio>
<source src="/voices/charactervoice.m4a"></source>
</audio>
</header>
</ul>
<ul>
<header id="play_2>
<img src="/img/characters/character2.png">
<audio>
<source src="/voices/charactervoice2.m4a"></source>
</audio>
</header>
</ul>
//javascript:
window.onload=function(){
for (let i = 1; i <= 2; i++){
var playHover = document.getElementById('play_' + i),
audios = document.querySelectorAll('audio');
console.log(audios);
playHover.addEventListener('mouseover', function() {
[].forEach.call(audios, function(audio) {
audio.volume = 0.05;
audio.play();
});
}, false);
}
}
It should only select the audio inside the playHover and not all the audio which is causing all the audio to play at once when hovering a card. You can try it like this (basing on how you written your code)
window.onload=function(){
for (let i = 1; i <= 2; i++){
let playHover = document.querySelector('#play_' + i),
let audio = playHover.querySelector('audio');
playHover.addEventListener('mouseover', function() {
audio.volume = 0.05;
audio.play();
}, false);
}
}
or you can code it like this so whenever you're going to add a header you won't have to edit your loop condition. (Ideally, you should place a class for each header and select that instead so if ever you are going to use the header element for another use, won't have problems with selections):
window.onload=function(){
const headers = document.querySelectorAll('header');
headers.forEach((e) => {
let audio = e.querySelector('audio');
e.addEventListener('mouseover', function() {
audio.volume = 0.05;
audio.play();
}, false);
});
}

Set Default Volume in script

I have a website that loops music on load, but it is too loud. I have a slider bar to change the music volume, but how would I default it to 25% of the slider?
WEBSITE
<audio id=music loop autoplay src="peep.mp3">
<p>If you are reading this, it is because your browser does not support the audio element.</p>
</audio>
<input id="vol-control" type="range" min="0" max="100" step="1" oninput="SetVolume(this.value)" onchange="SetVolume(this.value)"></input>
<script>
function SetVolume(val)
{
var player = document.getElementById('music');
console.log('Before: ' + player.volume);
player.volume = val / 100;
console.log('After: ' + player.volume);
}
</script>
Just create a script that set the volume:
var audio = document.getElementById("music");
audio.volume = 0.25;
If you are using the audio tags, just get the DOM Node in Javascript and manipulate the volume property
var audio = document.querySelector('audio');
// Getting
console.log(volume); // 1
// Setting
audio.volume = 0.5; // Reduce the Volume by Half
The number that you set should be in the range 0.0 to 1.0, where 0.0 is the quietest and 1.0 is the loudest.
input is a Void element and as such does not needs a closing </input>
You're using max, min, well, use also value.
Avoid using inline JavaScript. Keep you logic away from your markup.
init your function like setVolume()
use camelCase setVolume instead of PascalCase SetVolume, since it's a normal function, not a Method, Class or constructor...
const audio = document.getElementById('audio'),
input = document.getElementById('volume'),
setVolume = () => audio.volume = input.value / 100;
input.addEventListener("input", setVolume);
setVolume();
<audio id=audio loop autoplay src="//upload.wikimedia.org/wikipedia/en/4/45/ACDC_-_Back_In_Black-sample.ogg">Audio is not supported on your browser. Update it.</audio>
<input id=volume type=range min=0 max=100 value=25 step=1>
I think you'd also like this example.

HTML5 video custom controls: How to show the current frame of the video while dragging the seekbar

I have custom controls for a video.
See codepen.
Great. It works relatively well. However, I miss a functionality. When the video is paused and I drag slider on the seekbar, the video frames are not updating real time, only after you "put" the slider down (mousedown).
As you can see here, with the native html5 video functionality it's done like that: while you drag the bar, the video updates to the current frame your cursor is on. For me this would be quite important.
So, how could I make this happen? The problem lies in the nature of .addEventListener("change"), doesn't it?
<div class="row">
<div class="col-sm-4" id="video-container">
<!-- Video -->
<video id="video" muted>
<source src="https://www.w3schools.com/html/mov_bbb.mp4" type="video/mp4">
<p>
Your browser doesn't support HTML5 video.
</p>
</video>
<!-- Video Controls -->
<div id="video-controls">
<button type="button" id="play-pause" class="play"><img src="https://storage.googleapis.com/material-icons/external-assets/v4/icons/svg/ic_play_arrow_white_24px.svg"></button>
<input type="range" id="seek-bar" value="0">
<button type="button" id="full-screen"><img src=https://storage.googleapis.com/material-icons/external-assets/v4/icons/svg/ic_fullscreen_white_24px.svg></button>
</div>
</div>
</div>
<script type="text/javascript">
window.onload = function() {
// Video
var video = document.getElementById("video");
// Buttons
var playButton = document.getElementById("play-pause");
var fullScreenButton = document.getElementById("full-screen");
// Sliders
var seekBar = document.getElementById("seek-bar");
// Event listener for the play/pause button
playButton.addEventListener("click", function() {
if (video.paused == true) {
// Play the video
video.play();
// Update the button text to 'Pause'
$('img', playButton).attr("src","https://storage.googleapis.com/material-icons/external-assets/v4/icons/svg/ic_pause_white_24px.svg");
} else {
// Pause the video
video.pause();
// Update the button text to 'Play'
$('img', playButton).attr("src","https://storage.googleapis.com/material-icons/external-assets/v4/icons/svg/ic_play_arrow_white_24px.svg");
}
});
// Event listener for the full-screen button
fullScreenButton.addEventListener("click", function() {
if (video.requestFullscreen) {
video.requestFullscreen();
} else if (video.mozRequestFullScreen) {
video.mozRequestFullScreen(); // Firefox
} else if (video.webkitRequestFullscreen) {
video.webkitRequestFullscreen(); // Chrome and Safari
}
});
// Event listener for the seek bar
seekBar.addEventListener("change", function() {
// Calculate the new time
var time = video.duration * (seekBar.value / 100);
// Update the video time
video.currentTime = time;
});
// Update the seek bar as the video plays
video.addEventListener("timeupdate", function() {
// Calculate the slider value
var value = (100 / video.duration) * video.currentTime;
// Update the slider value
seekBar.value = value;
});
// Pause the video when the seek handle is being dragged
seekBar.addEventListener("mousedown", function() {
video.pause();
});
$('#video-controls').width($('video').width());
$('#seek-bar').width($('video').width() -105);
}
</script>
I got it done by changing the .addEventListener("change") to .addEventListener("input"), but maybe this question could be helpful for someone so I didn't delete it.

JavaScript Audio player, need seeking on progress bar

I have some code where the progress bar is linked to the audio paying; but i haven't worked out how to seek with the mouse cursor on the progress bar. Is there a way to do this in Legacy JavaScript?
JavaScript:
function play() {
document.getElementById('player').play();
}
function pause() {
document.getElementById('player').pause();
}
function updateProgress() {
var player = document.getElementById('player');
var progressbar = document.getElementById('seekbar');
progressbar.value = (player .currentTime / player .duration);
};
HTML:
<audio ontimeupdate="updateProgress()" src="music/fiji/lladep/apathy.mp3" id="player"></audio>
<button onClick="play()">Play</button>
<button onClick="pause()">Pause</button>
<progress id="seekbar" value="0" max="1"></progress>

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