How to play next audio when the current audio is finished playing? - javascript

I am currently trying to play another audio if the current audio is finished but I am not getting any success results would be appreciated if any suggestions is given,here is the below code :-
document.addEventListener('DOMContentLoaded', () => {
ms();
});
function ms() {
var btns = document.getElementsByClassName("pas");
for (var j = 0; j < btns.length; j++) {
document.addEventListener('play', function(e) {
var songs = document.getElementsByClassName("pas");
for (var i = 0; i < songs.length; i++) {
if (songs[i] != e.target) {
songs[i].pause();
}
}
}, true);
}
}
<audio class="pas" controls loop autoplay>
<source src="https://www.mboxdrive.com/Drake_-_One_Dance_(Lyrics)_ft._Wizkid_&_Kyla(128k).m4a" type="audio/mp3">
Your browser dose not Support the audio Tag
</audio>
<audio class="pas" controls loop autoplay>
<source src="https://www.mboxdrive.com/Coobie_-_Miss_You_(Official_Lyric_Video)(256k).mp3" type="audio/mp3">
Your browser dose not Support the audio Tag
</audio>
The above js is to allow only one audio to be played once. Anyway possible way to add any function to play another audio if the first one is finished?
You can try code demo here https://jsfiddle.net/mt1koznd/2/

Use the timeupdate event, and the .duration and .currentTime properties. If you intend to switch players, you need to remove the loop attribute and remove the autoplay attribute on all but one or all players will play at the same time. The example will work for an unlimited amount of players and will loop back to the starting player if the current player is the last one.
Details are commented in example
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style></style>
</head>
<body>
<audio class="song" controls>
<source src="https://www.mboxdrive.com/Drake_-_One_Dance_(Lyrics)_ft._Wizkid_&_Kyla(128k).m4a" type="audio/mp3">
</audio>
<audio class="song" controls>
<source src="https://www.mboxdrive.com/Coobie_-_Miss_You_(Official_Lyric_Video)(256k).mp3" type="audio/mp3">
</audio>
<script>
// Collect all .song into a NodeList then convert it into a real array
const songs = [...document.querySelectorAll('.song')];
// Bind the timeupdate event to each .song
songs.forEach(song => song.ontimeupdate = nextSong);
// Event handler
function nextSong(e) {
// Get player's full duration in seconds
const end = this.duration;
// Get the current time spent playing in seconds
let now = this.currentTime;
// If the time playing reaches the duration...
if (end <= now) {
// Get the index position of player
const position = songs.indexOf(this);
// If the player is the last one start play on the first player
if (position === songs.length - 1) {
songs[0].play();
// Otherwise start ply on the next player
} else {
songs[position + 1].play();
}
}
}
</script>
</body>
</html>

Related

Multiple HTML5 videos audio captions not working correctly

I am adding multiple HTML5 videos onto a webpage.
The code I am replicating is from this recommended accessible approach. http://jspro.brothercake.com/audio-descriptions/ The video plays fine, and audio captions work, but when I add a new video to the same page the second video does not play the audio captions at all. Does anyone have suggestions on how I can fix this issue?
<video id="video" preload="auto" controls="controls"
width="640" height="360" poster="./media/HorribleHistories.jpg">
<source src="./media/HorribleHistories.mp4" type="video/mp4" />
<source src="./media/HorribleHistories.webm" type="video/webm" />
</video>
<audio id="audio" preload="auto">
<source src="./media/HorribleHistories.mp3" type="audio/mp3" />
<source src="./media/HorribleHistories.ogg" type="audio/ogg" />
</audio>
<script type="text/javascript">
(function()
{
//get references to the video and audio elements
var video = document.getElementById('video');
var audio = document.getElementById('audio');
//if media controllers are supported,
//create a controller instance for the video and audio
if(typeof(window.MediaController) === 'function')
{
var controller = new MediaController();
audio.controller = controller;
video.controller = controller;
}
//else create a null controller reference for comparison
else
{
controller = null;
}
//reduce the video volume slightly to emphasise the audio
audio.volume = 1;
video.volume = 0.8;
//when the video plays
video.addEventListener('play', function()
{
//if we have audio but no controller
//and the audio is paused, play that too
if(!controller && audio.paused)
{
audio.play();
}
}, false);
//when the video pauses
video.addEventListener('pause', function()
{
//if we have audio but no controller
//and the audio isn't paused, pause that too
if(!controller && !audio.paused)
{
audio.pause();
}
}, false);
//when the video ends
video.addEventListener('ended', function()
{
//if we have a controller, pause that
if(controller)
{
controller.pause();
}
//otherwise pause the video and audio separately
else
{
video.pause();
audio.pause();
}
}, false);
//when the video time is updated
video.addEventListener('timeupdate', function()
{
//if we have audio but no controller,
//and the audio has sufficiently loaded
if(!controller && audio.readyState >= 4)
{
//if the audio and video times are different,
//update the audio time to keep it in sync
if(Math.ceil(audio.currentTime) != Math.ceil(video.currentTime))
{
audio.currentTime = video.currentTime;
}
}
}, false);
})();
</script>
So your problem is to do with how you are grabbing the elements in the first place.
var video = document.getElementById('video');
var audio = document.getElementById('audio');
What you are doing is grabbing a single item on the page with the ID of "video" (same for "audio").
IDs have to be unique, so what you want to do is use classes instead.
<video class="video" preload="auto" controls="controls"
width="640" height="360" poster="./media/HorribleHistories.jpg">
See I changed the ID to a class.
Now any element with the class "video" can be used in our code.
However we do need to modify our code a bit as now we have multiple items to bind to.
please note the below is to give you an idea of how you loop items etc. You would need to rewrite your code to move each of the steps into functions etc. as your original code is not designed to work with multiple items
(function()
{
//get references to every single video and audio element
var videos = document.querySelectorAll('.video');
var audios = document.querySelectorAll('.audio');
// loop through all videos adding logic etc.
for(x = 0; x < videos.length; x++){
// grab a single video from our list to make our code neater
var video = videos[x];
if(typeof(window.MediaController) === 'function')
{
var controller = new MediaController();
video.controller = controller;
} else {
controller = null;
}
video.volume = 0.8;
//...etc.
}
})();
Quick Tip:
I would wrap your <video> and <audio> elements that are related in a <div> with a class (e.g. class="video-audio-wrapper").
This way you can change your CSS selector to something like:
var videoContainers = document.querySelectorAll('.video-audio-wrapper');
Then loop through them instead and check if they have a video and / or audio element
for(x = 0; x < videoContainers.length; x++){
var thisVideoContainer = videoContainers[x];
//query this container only - we can use `querySelector` as there should only be one video per container and that returns a single item / the first item it finds.
var video = thisVideoContainer.querySelector('video');
var audio = thisVideoContainer.querySelector('audio');
//now we can check if an element exists
if(video.length == 1){
//apply video logic
}
if(audio.length == 1){
//apply audio logic
}
// alternatively we can check both exist if we have to have both
if(video.length != 1 || audio.length != 1){
// we either have one or both missing.
// apply any logic for when a video / audio element is missing
//using "return" we can exit the function early, meaning all code after this point is not run.
return false;
}
///The beauty of this approach is you could then just use your original code!
}
Doing it this way you could recycle most of your code.
Thank you for your suggestions in changing the ID's into classes and adding the video wrapper <div> to the video container. That all makes sense in grouping each video on 1 page. I updated the the following code, but the audio captions won't play at all. The video plays and pauses fine, and the volume works. I am also not getting any syntax errors in the browser console. Here's what I got for my HTML and JS. I appreciate your help/feedback.
<div class="video-container-wrapper">
<div class="video-container">
<video class="video" preload="auto" controls="controls" width="640" height="360" poster="img/red-zone-thumb.png">
<source src="https://player.vimeo.com/external/395077086.hd.mp4?s=1514637c1ac308a950fafc00ad46c0a113c6e8be&profile_id=175" type="video/mp4">
<track kind="captions" label="English captions" src="captions/redzone-script.vtt" srclang="en" default="">
</video>
<audio class="audio" preload="auto">
<source src="captions/redzone-message.mp3" type="audio/mp3">
</audio>
</div>
</div>
Javascript:
var videoContainers = document.querySelectorAll('.video-container-wrapper');
for (x = 0; x < videoContainers.length; x++) {
var thisVideoContainer = videoContainers[x];
//query this container only - we can use `querySelector` as there should only be one video per container and that returns a single item / the first item it finds.
var video = thisVideoContainer.querySelector('video');
var audio = thisVideoContainer.querySelector('audio');
//now we can check if an element exists
if (video.length == 1) {
//apply video logic
//reduce the video volume slightly to emphasise the audio
video.volume = 0.8;
//when the video ends
video.addEventListener('ended', function () {
video.pause();
}, false);
}
if (audio.length == 1) {
//apply audio logic
audio.volume = 1;
//when the video plays
video.addEventListener('play', function () {
if (audio.paused) {
audio.play();
}
}, false);
// when the video ends
video.addEventListener('ended', function () {
audio.pause();
}, false);
//when the video time is updated
video.addEventListener('timeupdate', function () {
if (audio.readyState >= 4) {
//if the audio and video times are different,
//update the audio time to keep it in sync
if (Math.ceil(audio.currentTime) != Math.ceil(video.currentTime)) {
audio.currentTime = video.currentTime;
}
}
}, false);
}
}

HTML5 Video - pause for a few seconds then continue playback

I have a HTML5 video element in my page and what I'd like to happen is when it reaches the 3 second mark, it needs to pause for 2 seconds and then continue playback.
The video length is about 8 seconds.
<video id="video" playsinline autoplay muted loop>
<source src="video.mp4" type="video/mp4"/>
<source src="video.webm" type="video/webm"/>
</video>
This does it
const video = document.getElementById('myVideo');
function playVid() {
video.play();
window.setTimeout(pauseVid, 3000);
}
function play() {
video.play();
}
function pauseVid() {
video.pause();
window.setTimeout(play, 5000);
}
setTimeout() .currentTime & timeupdate
Go to the link above to understand why setTimeout() ain't so great.
.currentTime Property
This property is used by <audio> and <video> tags to get/set playback time in seconds. In the following demo it is used to get the time:
var t = this.currentTime;
timeupdate Event
This event fires 4 times a second while an <audio> or <video> tag is playing. In the demo both a <video> and <audio> tag are registered to to the timeupdate event:
video.addEventListener("timeupdate", tick);
timer.addEventListener("timeupdate", tock);
Setup
[controls] Attribute
Added so the time can be reviewed as the demo runs, it's optional and recommended that it not be used in production.
<audio> Tag
An <audio> tag has been added as a timer, The attributes [muted] and [autoplay] are required:
<audio id='timer' src='https://od.lk/s/NzlfOTEwMzM5OV8/righteous.mp3' muted controls autoplay></audio>
Both tags will start playing and are listening to the timeupdate event and will call a function at a predetermined time:
function tick(e) {
var t = this.currentTime;
if (t >= 3) {
this.pause();
video.removeEventListener("timeupdate", tick);
}
}
function tock(e) {
var t = this.currentTime;
if (t >= 5) {
video.play();
timer.removeEventListener("timeupdate", tock);
}
}
Basically when the <video> and <audio> tags are triggered every 250ms, they are calling those functions:
<video> calls function tick()
if the playback time is 3 or more seconds it pauses.
to avoid constant triggering every 250ms, the eventListener is removed.
<audio> calls function tock()
if the playback time is 5 or more seconds it will play the <video>.
for the same reason as the <video>, the eventListener is removed.
Demo
var video = document.getElementById('video');
var timer = document.getElementById('timer');
video.addEventListener("timeupdate", tick);
timer.addEventListener("timeupdate", tock);
function tick(e) {
var t = this.currentTime;
if (t >= 3) {
this.pause();
video.removeEventListener("timeupdate", tick);
}
}
function tock(e) {
var t = this.currentTime;
if (t >= 5) {
video.play();
timer.removeEventListener("timeupdate", tock);
}
}
<video id="video" playsinline muted loop controls autoplay width='300'>
<source src="https://html5demos.com/assets/dizzy.mp4" type="video/mp4"/>
</video>
<audio id='timer' src='https://od.lk/s/NzlfOTEwMzM5OV8/righteous.mp3' muted controls autoplay></audio>

Looping two audio objects with a pause in between each one

I've got two audio elements on a page:
<audio id="voice1" class="voice1 voice" controls>
<source src="1.mp3" type="audio/mpeg">
</audio>
<audio id="voice1" class="voice2 voice" controls>
<source src="2.mp3" type="audio/mpeg">
</audio>
I want to play the first one, pause for 5 seconds, play the second one, pause for a further 5 seconds then repeat the whole process a fixed number of times.
jQuery(document).ready(function(){
for (j = 0; j < 100; ++j) {
var audioArray = document.getElementsByClassName('voice');
var i = 0;
audioArray[i].play();
for (i = 0; i < audioArray.length - 1; ++i) {
audioArray[i].addEventListener('ended', function(e){
// pause here for 5 seconds
var currentSong = e.target;
var next = $(currentSong).nextAll('audio');
if (next.length) $(next[0]).trigger('play');
});
}
});
I have experimented with setInterval and setTimeout but I can't get this pause to work. I have considered just playing a quiet mp3 file for 5 seconds but this seems daft. Can anyone recommend a suitable approach?

Resume video playback after pause in JavaScript/HTML5?

I'm trying to pause a video and then resume the playback. But I presume I somehow need to clear the pause function? I've tried iterations of myVideo.play() and I can get it to play but only for short bursts. Any help would be much welcome.
<!DOCTYPE html>
<html>
<head>
<title> Html5 Video Test </title>
<meta charset="UTF-8">
</head>
<body> <
<div style="text-align:center">
<button onclick="playPause()">Play/Pause</button>
<video id="video1" width="420" autoplay>
<source src="test.mov" type="video/mov">
<source src="test.mp4" type="video/mp4">
Your browser does not support HTML5 video.
</video>
</div>
<script>
var myVideo = document.getElementById("video1");
myVideo.addEventListener("timeupdate", function(){
if(this.currentTime >= 1 * 2) {
this.pause();
}
});
</script>
</body>
</html>
If I understand correctly, you want your event listener to only fire once (so when you next play the video, it doesn't just immediately get paused again). If so, give this a shot:
var myVideo = document.getElementById("video1");
// Give this function a name so we can refer to it later.
function pauseOnce() {
if (this.currentTime >= 1 * 2) {
this.pause();
// Our work is done. Remove the event listener. (We need a reference to
// the function here.)
this.removeEventListener("timeupdate", pauseOnce);
}
}
myVideo.addEventListener("timeupdate", pauseOnce);

play Audio tag onload in a specific time(ogg/mp3) using javascript

Load Audio tag in a specific time(mp3) using javascript.
Current code bellow, complety ignores currentTime.
My objective is to autoplay a mp3 file based on time(seconds) of the computer hardware clock.
<!DOCTYPE html>
<html>
<body>
<button onclick="setCurTime()" type="button">Set time position to 5 seconds</button>
<br>
<audio id="audio1" controls="controls">
<source src="http://attackbeat.com/audio/Masayume%20Chasing.mp3" type="audio/mp3">
Your browser does not support HTML5 video.
</audio>
<script>
var time = new Date();
var timex = time.getSeconds();
myAudio=document.getElementById("audio1");
window.onload = function () {
myAudio.play();
myAudio.currentTime=10;
}
function setCurTime()
{
myAudio.currentTime=timex;
myAudio.play();
}
</script>
</body>
</html>
You can seek to the given time only once the meta data is available:
var audio = document.getElementById('audio1');
audio.onloadedmetadata = function() {
audio.currentTime = new Date().getSeconds(); // autoplay based on current time (seconds)
audio.play();
};

Categories

Resources