Do Action After audio.ended - javascript

Trying to learn some simple JS stuff with audio since I do a lot of audio work I figured I would learn how to embed some into a site of mine, not to mention just brush up on some simple web programming.
I wanted to have an action after the audio file finished playing however a while(1) loop checking audio.ended immediately crashes.
I decided to use setInterval to check every second however this does not seem to work either. No crash but nothing happens. I've checked through the Mozilla documentation and as far as I can see with my limited experience there is no obvious solution.
var audio = document.createElement('audio');
audio.id = 'audio';
audio.src = 'track01.mp3';
audio.play();
setInterval(checkFinished(), 1000);
function checkFinished()
{
if(audio.ended == false)
{
document.write(audio.ended.toString());
}
else
{
document.write(audio.ended.toString());
foo();
}
}

You should use an Event, instead.
var audio = document.createElement('audio'); audio.id = 'audio';
audio.src = 'track01.mp3';
document.body.appendChild(audio); // append somewhere else if wanted
audio.play();
audio.onended = function(){
console.log('You do say.');
}

As said by PHPglue, you can use .onended.
here's an example:
<audio id="myAudio" controls>
<source src="track01.mp3" type="audio/mpeg">
</audio>
<script>
var aud = document.getElementById("myAudio");
aud.onended = function() {
alert("The audio has ceased");
};
</script>
(I don't like needless js, but the script part is still applicable of you just use js for the audio)
Check out http://www.w3schools.com/tags/av_event_ended.asp for some info

Related

How do I loop a random audio player when the audio has finished playing?

I've been trying to figure out a way to make one song transition to the next, how would I go about this?
I haven't tried much. I'm relatively inexperienced in Javascript so my attempts have generally been futile.
var numberOfSongs = 4
var sound = new Array(numberOfSongs+1)
sound[0]= "skytop.mp3"
sound[1]= "ac.mp3"
sound[2]= "forgotten.mp3"
sound[3]= "miserable.mp3"
function randomNumber(){
var randomLooper = -1
while (randomLooper < 0 || randomLooper > numberOfSongs || isNaN(randomLooper)){ randomLooper = parseInt(Math.random()*(numberOfSongs+1))
}
return randomLooper
}
var randomsub = randomNumber()
var soundFile = sound[randomsub]
document.write ('<EMBED src= "' + soundFile + '" hidden=true type="audio/mpeg" autostart=true loop=true>')
This is what I'm working with, any pointers would be much appreciated.
This isn't a complete answer (which would take a while!), but it might help you get started. Take a look at these APIs:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLAudioElement
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement
The way you play a clip is like this:
var audio = new Audio('url/to/my/audio.mp3');
audio.play();
That's gets the audio playing. But since you want to know when the music stops, in order to play the next clip, before you start playing, add an event listener:
audio.addEventListener('ended', (event) => {
// Your code to start playing the next clip goes here.
});
You can get much fancier, of course. There's enough audio processing capability available that you could crossfade your selections, not just play them sequentially.

Why is sound not playing in angular?

I'm trying to get an alert sound to play when a certain condition is met. This condition is being met when I test with an alert() in place of the sound. Code snippet:
if ($scope.incomplete > $scope.incomplete_old) {
$scope.playAudio = function() {
var audio = new Audio("{% static 'ping.mp3' %}");
audio.play();
}
}
Am I missing something here? I don't understand why the sound isn't playing. I'm testing the site locally in Chrome. Is there some other configuration I overlooked?
according to your code example $scope.playAudio method is never called. Therefor your audio.play() will never be executed. To play the sound you have to call the $scope.playAudio method.
basically you can do either
$scope.playAudio()
of you let the function invoke itself
$scope.playAudio = function() {
var audio = new Audio("{% static 'ping.mp3' %}");
audio.play();
}()
further reading: https://www.w3schools.com/js/js_functions.asp

Create Seamless Loop of Audio - Web

I want to create a seamless loop of an audio file. But in all approaches I used so far, there was a noticeable gap between end & start.
This is what I tried so far:
First approach was to use the audio in the HTML and it loops but there is still a noticeable delay when going from the end of the track to the beginning.
<audio loop autoplay>
<source src="audio.mp3" type="audio/mpeg">
<audio>
Then I tried it from JavaScript with the same result:
let myAudio = new Audio(file);
myAudio.loop = true;
myAudio.play();
After that I tried this (according to this answer)
myAudio.addEventListener(
'timeupdate',
function() {
var buffer = .44;
if (this.currentTime > this.duration - buffer) {
this.currentTime = 0;
this.play();
}
},
false
);
I played around with the buffer but I only got it to reduce the gap but not leave it out entirely.
I turned to the library SeamlessLoop (GitHub) and got it to work to loop seamlessly in Chromium browsers (but not in the latest Safari. Didn't test in other browsers). Code I used for that:
let loop = new SeamlessLoop();
// My File is 58 Seconds long. Btw there aren't any gaps in the file.
loop.addUri(file, 58000, 'sound1');
loop.callback(soundsLoaded);
function soundsLoaded() {
let n = 1;
loop.start('sound' + n);
}
EDIT: I tried another approach: Looping it trough two different audio elements:
var current_player = "a";
var player_a = document.createElement("audio");
var player_b = document.createElement("audio");
player_a.src = "sounds/back_music.ogg";
player_b.src = player_a.src;
function loopIt(){
var player = null;
if(current_player == "a"){
player = player_b;
current_player = "b";
}
else{
player = player_a;
current_player = "a";
}
player.play();
/*
3104.897 is the length of the audio clip in milliseconds.
Received from player.duration.
This is a different file than the first one
*/
setTimeout(loopIt, 3104.897);
}
loopIt();
But as milliseconds in browsers are not consistent or granular enough this doesn't work too well but it does work much better than the normal "loop" property of the audio.
Can anyone guide me into the right direction to loop the audio seamlessly?
You can use the Web Audio API instead. There are a couple of caveats with this, but it will allow you to loop accurately down to the single sample level.
The caveats are that you have to load the entire file into memory. This may not be practical with large files. If the files are only a few seconds it should however not be any problem.
The second is that you have to write control buttons manually (if needed) as the API has a low-level approach. This means play, pause/stop, mute, volume etc. Scanning and possibly pausing can be a challenge of their own.
And lastly, not all browsers support Web Audio API - in this case you will have to fallback to the regular Audio API or even Flash, but if your target is modern browsers this should not be a major problem nowadays.
Example
This will load a 4 bar drum-loop and play without any gap when looped. The main steps are:
It loads the audio from a CORS enabled source (this is important, either use the same domain as your page or set up the external server to allow for cross-origin usage as Dropbox does for us in this example).
AudioContext then decodes the loaded file
The decoded file is used for the source node
The source node is connected to an output
Looping is enabled and the buffer is played from memory.
var actx = new (AudioContext || webkitAudioContext)(),
src = "https://dl.dropboxusercontent.com/s/fdcf2lwsa748qav/drum44.wav",
audioData, srcNode; // global so we can access them from handlers
// Load some audio (CORS need to be allowed or we won't be able to decode the data)
fetch(src, {mode: "cors"}).then(function(resp) {return resp.arrayBuffer()}).then(decode);
// Decode the audio file, then start the show
function decode(buffer) {
actx.decodeAudioData(buffer, playLoop);
}
// Sets up a new source node as needed as stopping will render current invalid
function playLoop(abuffer) {
if (!audioData) audioData = abuffer; // create a reference for control buttons
srcNode = actx.createBufferSource(); // create audio source
srcNode.buffer = abuffer; // use decoded buffer
srcNode.connect(actx.destination); // create output
srcNode.loop = true; // takes care of perfect looping
srcNode.start(); // play...
}
// Simple example control
document.querySelector("button").onclick = function() {
if (srcNode) {
srcNode.stop();
srcNode = null;
this.innerText = "Play";
} else {
playLoop(audioData);
this.innerText = "Stop";
}
};
<button>Stop</button>
There is a very simple solution for that, just use loopify it makes use of the html5 web audio api and works perfectly well with many formats, not only wav as the dev says.
<script src="loopify.js" type="text/javascript"></script>
<script>
loopify("yourfile.mp3|ogg|webm|flac",ready);
function ready(err,loop){
if (err) {
console.warn(err);
}
loop.play();
}
</script>
This will automatically play the file, if you want to have start and stop buttons for example take a look at his demo

javascript - video play not working in setInterval

I am trying to play video using .play().
This is for in app with mraid, only native javascript.
I'm trying to play a video with .play(), it works only when the video is loaded.
var video = document.getElementById('video');
video.play();
the above simple 2 lines works like a charm, only when the video is loaded.
Therefore i have to make sure the video is loaded by using setInterval
var autoplay = setInterval(function(){
var video = document.getElementById('extVideo-tab1');
if(video !== null)
{
video.play();
clearInterval(autoplay);
}
},500);
Im very certain that it went into the if, but the video is not played.
Can't figure out why it is not working.
Please help, THANK YOU!
as an alternative, you could try using readyState, as:
var video = document.getElementById('video');
if( video.readyState === 4) {
// 4 -> HAVE_ENOUGH_DATA
//Enough data is available, the media can be played through to the end without interruption.
video.play();
}
Depending on your use case I suggest one of the two following potential solutions:
If you always want it to play right away, do:
video.autoplay = true;
or you could use readyState:
var autoplay = setInterval(function(){
var video = document.getElementById('extVideo-tab1');
if(video.readyState === 4)
{
video.play();
clearInterval(autoplay);
}
},500);
Is there a reason you cant use the autoplay attribute?
https://developer.mozilla.org/en/docs/Web/HTML/Element/video
Regardless you should use the onloadedmetadata event or similar that way you know when you can start playing or seek to a point (unless im missing something?)
document.getElementById('extVideo-tab1').addEventListener('loadedmetadata', function() {
this.play();
}, false)

Audio in a tool tip/hover?

I would like to include audio that will automatically play when the user scrolls over. I have not found a tooltip that will do this. Does anyone know of a way to accomplish this?
(Note: The user will be warned about the audio before they have access to the page.)
UPDATE
I got this working thanks to Bakudan - хан ювиги. But is there a flash fall back available using Bakudan - хан ювиги's method? Thanks!
UPDATE 2
Using Bakudan - хан ювиги's recommended method for adding a flash fallback using swfobject leaves me a bit confused. My lack of javascript knowledge is where I get lost. Here is the code I am using for my audio:
<script>
// Mouseover/ Click sound effect- by JavaScript Kit (www.javascriptkit.com)
// Visit JavaScript Kit at http://www.javascriptkit.com/ for full source code
var html5_audiotypes={ //define list of audio file extensions
"mp3": "audio/mpeg",
"ogg": "audio/ogg",
}
function createsoundbite(sound){
var html5audio=document.createElement('audio')
if (html5audio.canPlayType){ //check support for HTML5 audio
for (var i=0; i<arguments.length; i++){
var sourceel=document.createElement('source')
sourceel.setAttribute('src', arguments[i])
if (arguments[i].match(/\.(\w+)$/i))
sourceel.setAttribute('type', html5_audiotypes[RegExp.$1])
html5audio.appendChild(sourceel)
}
html5audio.load()
html5audio.playclip=function(){
html5audio.pause()
html5audio.currentTime=0
html5audio.play()
}
return html5audio
}
else{
return {playclip:function(){throw new Error(
"Your browser doesn't support HTML5 audio unfortunately")}}
}
}
//Initialize sound clips with 1 fallback file each:
var mouseoversound=createsoundbite(
"/messages4u/2011/images/october/laugh.ogg",
"/messages4u/2011/images/october/laugh.mp3")
</script>
I changed the else to the flash instead of the error message. How do I change this using swfobject to play the flash audio file? I am a bit lost by that.
Thanks for the help!
This is a good start. I`ve made a demo. If the audio is a little bit longer, add stopclip function to the createsoundbite function and then add it to the .mouseleave.
Edit:
To add flash change the else part. I'm very familiar with flash, but basically use one of the following:
create object - "document.createElement("object");... etc"
or which I think is better use swfobject
Here's a version that plays sound in older browsers and does not require flash:
var sound = document.createElement("audio");
if (!("src" in sound)) {
sound = document.createElement("bgsound");
}
document.body.appendChild(sound);
function playSound(src) {
sound.src = src;
sound.play && sound.play();
}
...
playSound("/sounds/something.mp3");
Edit: Here's a version that uses .hover() to play the sound when the mouse hovers over your element:
$(function) {
var sound = document.createElement("audio");
if (!("src" in sound)) {
sound = document.createElement("bgsound");
}
document.body.appendChild(sound);
$(".playable").hover(function() {
sound.src = this.soundFile;
sound.play && sound.play();
}, function() {
sound.src = "";
});
});
Set up your elements that you want to play a sound with a class of "playable" and custom attribute "soundFile" containing the source url for the sound file:
<span class="playable" soundFile="/sounds/something.mp3">Something</span>
<span class="playable" soundFile="/sounds/somethingElse.mp3">Something else</span>
soundmanager2

Categories

Resources