Why is sound not playing in angular? - javascript

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

Related

Playing audio with javascript

I am trying to play a beep sound a minute after user has come on the page of my website. I found the solution here https://stackoverflow.com/a/18628124/912359
Here's my code:
$(document).ready(function(){
setTimeout(function () {
try{
if(!$(".facebook-chat").hasClass("active")){
$(".facebook-chat").addClass("active");
var audio = new Audio("/sound/chat.mp3");
audio.play();
}
}catch(e){
}
}, 60000);
}):
This throws an exception:
Uncaught (in promise) DOMException
Strangely, once I load the sound file separately in my browser and come back to the page, it works perfectly. Any ideas how I can fix it.
[Edit]
The issue is that user has to interact with the browser before the sound can be played. So I put the same code under click event of the body and it works. But the same doesn't work on scroll event either. I guess chrome doesn't consider scroll a user interaction. Can anyone add what other interactions can be used to trigger this?
Also, how is it working if I load the audio file in a separate window and come back to my page.
You can try loading the audio when the document is ready and then play it later only if the resource is loaded (for this check you can register a callback on onloadeddata). Otherwise, if resource is not loaded, you can try loading it again.
$(document).ready(function()
{
let aud = new Audio('https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3');
let canPlay = false;
aud.onloadeddata = () => (console.log("audio loaded"), canPlay = true);
setInterval(function()
{
if (canPlay)
aud.play();
else
aud = new Audio('https://dl.dropboxusercontent.com/s/1cdwpm3gca9mlo0/kick.mp3');
}, 3000);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Best solution I could come up with when I tried the same was:
const playPromise = audio.play();
if (playPromise !== null){
playPromise.catch(function() { audio.play(); })
}
But sometimes (One out of ten) the second audio.play() where also uncaught and the audio did not play either. I suggest you made a loop that stops only when the Promise is finally caught.

PhoneGap Media Plugin - can you detect when url stream has loaded?

I been having some issues getting my audio player to work correctly in iOS and Android using the PhoneGap Media plugin through Build 3.1
I have play and stop buttons that work fine but when you hit play there is a slight delay as the audio url loads and it freezes the OS. I can kind of cope with that as its a short delay so I thought I'd pop up a loading icon onscreen.
Ive posted a few time here trying to get the JS to work as im no expert but just now I've realised that there is nothing in my code to check if the audio is actually PLAYING!
The playAudio function loads in the audio and then sets the play button to a stop button. I thought function success() {meant it was playing but it actually means it FINISHED playing.
In my code when the link to the audio is clicked the loader function makes a spinner appear on screen and I thought 'success' would turn the loader off because its loaded when in fact whats happening is the laoder stays on and goes away after the track has finished!
I've realized I need a way of detecting if the track is actually PLAYING!
How do I do that?!?!!
Heres the function:
function loadPlay(src, trackName) {
loader();
playAudio(src, trackName);
}
function loader() {
// make a loader spinner appear as track loads
$(".loading").addClass("loadingnow");
}
function playAudio(src,trackname) {
// for Android
if (audioPlaying === false) {
if (device.platform == 'Android') {
src = '/android_asset/www/' + src;
}
media = new Media(src, success, error_error);
media.play();
//add playing class so play button is replaced with stop button
document.getElementById(trackname).parentNode.className="playing";
audioPlaying = true;
} else {
//audio is already playing
}
}
function success() {
// track isplaying so remove the stop button put play button back
$(".playing").removeClass("playing");
// now track is playing remove the loader spinner
$(".loading").removeClass("loadingnow");
audioPlaying = false;
}
function error_error(e) {
//alert('great error');
//alert(e.message);
}
function stopAudio() {
// stop playing track
if (media) {
media.stop();
audioPlaying = false;
}
}
Heres a link to the PhoneGap Media plugin API:
http://docs.phonegap.com/en/3.1.0/cordova_media_media.md.html#Media
Do I need to use this bit?
Media.MEDIA_STARTING = 1;
Media.MEDIA_RUNNING = 2;
Media.MEDIA_PAUSED = 3;
Media.MEDIA_STOPPED = 4;
From the docs:
The following constants are reported as the only parameter to the mediaStatus callback function.
Media.MEDIA_NONE = 0;
Media.MEDIA_STARTING = 1;
Media.MEDIA_RUNNING = 2;
Media.MEDIA_PAUSED = 3;
Media.MEDIA_STOPPED = 4;
The mediaStatus callback is an optional 3rd callback supplied in your Media constructor...
media = new Media(src, success, error_error, status_change);
function status_change(code) {
switch (code) :
case Media.MEDIA_STOPPED : doSomething(); break;
}
From what I can tell, ilovett's answer might not work for you, because the doSomething() function will get called in two other cases:
When someone stops the music with a media.stop()
When the media gets released (media.release()) on android (not sure about others, but iOS wont call it).
the way I'm doing it is setting a variable to make sure that the function is not getting called accidentally.

Why isn't my audio rewinding?

I'm having a bit of trouble rewinding audio in Javascript. I basically have a countdown that beeps each second as it gets towards the end of the countdown.
I tried using;
var bip = new Audio("http://www.soundjay.com/button/beep-7.wav");
bip.play();
but it didn't beep every second which I'm guessing has something to do withit having to load a new sound every second. I then tried loading the sound externally and triggering it with the following code.
bip.pause();
bip.currentTime = 0;
console.log(bip.currentTime);
bip.play();
but this only plays the sound once then completely fails to rewind it (this is shown by the console logging a time of 0.19 seconds after the first playthrough).
Is there something I'm missing here?
In google chrome I noticed that it only works if you have the audio file in same domain. I have no problems if the audio file is in same domain. Event setting .currentTime works.
Cross-domain:
var bip = new Audio("http://www.soundjay.com/button/beep-7.wav");
bip.play();
bip.currentTime; //0.10950099676847458
bip.currentTime = 0;
bip.currentTime; //0.10950099676847458
Same-domain:
var bip = new Audio("beep-7.wav");
bip.play();
bip.currentTime; //0.10950099676847458
bip.currentTime = 0;
bip.currentTime; //0
I tried googling for a while and could find nothing in specs about this or even any discussion.
when I want rewind I simply load the audio again:
my_audio.load()
*btw, I also use a eventlistener for 'canplay' to trigger the my_audio.play(). It seems that this is necessary in android, and maybe other devices also*
To further dsdsdsdsd's answer with a bit of paint-by-numbers for the "whole shebang"
NOTE: In my app, loc1 is a dummy that refers to the song's stored location
// ... code before ...
tune = new Audio(loc1); // First, create audio event using js
// set up "song's over' event listener & action
tune.addEventListener('ended', function(){
tune.load(); //reload audio event (and reset currentTime!)
tune.play(); //play audio event for subsequent 'ended' events
},false);
tune.play(); // plays it the first time thru
// ... code after ...
I spent days and days trying to figure out what I was doing wrong, but it all works fine now... at least on the desktop browsers...
As of Chrome version 37.0.2062.120 m, the behaviour described by #Esailija has not changed.
I workaround this issue by encoding the audio data in base64 encoding and feed the data to Audio() using data: URL.
Test code:
snd = new Audio('data:audio/ogg;base64,[...base64 encoded data...]');
snd.onloadeddata = function() {
snd.currentTime = 0;
snd.play();
setTimeout(function() {
snd.currentTime = 0;
snd.play();
}, 200);
};
(I am surprised that there are no bug reports or references on this matter... or maybe my Google-fu is not strong enough.)

Reference URL with JavaScript to play sound?

Im using soundcloud dot com to upload my sounds. i want to press a button within my mobile application and have that sound play.
So basically i want my sound to be referenced from the URL that I am given when the button is pressed by the user.
I need to do it with Javascript only. No HTML 5 please. Any help is greatly appreciated cause this is Xtremely frustrating. Any ideas? Thanks in advance.
It's pretty simple to get started really:
function playSound(url) {
var a = new Audio(url);
a.play();
}
Use that as whatever event handler you want for your application. Of course, I'd hope you'd want to do more than just play (for example, maybe pause would be good too?), but it's a start.
let sound = new Audio("http://sound.com/mySound.mp3");
//on play event:
sound.onplay = () => {
};
//on pause event:
sound.onpause = () => {
};
//on end event:
sound.onended = () => {
};
//play:
sound.play();
//pause:
sound.pause();
//stop:
sound.pause();
sound.currentTime = 0;
Use jPlayer to play sound using Javascript. This will take you a lot of time and frustration.
jplayer.org/
Here's what your code might look like with jPlayer. Note: You're not forced to use a skin with jPlayer because all it is is just an API to play audio.
Example code to play a video or audio on load.
$(function() { // executed when $(document).ready()
$("#jpId").jPlayer( {
ready: function () {
$(this).jPlayer("setMedia", {
m4v: "http://www.myDomain.com/myVideo.m4v" // Defines the m4v url
}).jPlayer("play"); // Attempts to Auto-Play the media
},
supplied: "m4v",
swfPath: "jPlayer/js"
});
});
http://jplayer.org/latest/developer-guide/

Problems preloading audio in Javascript

I'm trying to make a cross-device/browser image and audio preloading scheme for a GameAPI I'm working on. An audio file will preload, and issue a callback once it completes.
The problem is, audio will not start to load on slow page loads, but will usually work on the second try, probably because it cached it and knows it exists.
I've narrowed it down to the audio.load() function. Getting rid of it solves the problem, but interestingly, my motorola droid needs that function.
What are some experiences you've had with HTML5 audio preloading?
Here's my code. Yes, I know loading images in a separate function could cause a race condition :)
var resourcesLoading = 0;
function loadImage(imgSrc) {
//alert("Starting to load an image");
resourcesLoading++;
var image = new Image();
image.src = imgSrc;
image.onload = function() {
//CODE GOES HERE
//alert("A image has been loaded");
resourcesLoading--;
onResourceLoad();
}
}
function loadSound(soundSrc) {
//alert("Starting to load a sound");
resourcesLoading++;
var loaded = false;
//var soundFile = document.createElement("audio");
var soundFile = document.createElement("audio");
console.log(soundFile);
soundFile.autoplay = false;
soundFile.preload = false;
var src = document.createElement("source");
src.src = soundSrc + ".mp3";
soundFile.appendChild(src);
function onLoad() {
loaded = true;
soundFile.removeEventListener("canplaythrough", onLoad, true);
soundFile.removeEventListener("error", onError, true);
//CODE GOES HERE
//alert("A sound has been loaded");
resourcesLoading--;
onResourceLoad();
}
//Attempt to reload the resource 5 times
var retrys = 4;
function onError(e) {
retrys--;
if(retrys > 0) {
soundFile.load();
} else {
loaded = true;
soundFile.removeEventListener("canplaythrough", onLoad, true);
soundFile.removeEventListener("error", onError, true);
alert("A sound has failed to loaded");
resourcesLoading--;
onResourceLoad();
}
}
soundFile.addEventListener("canplaythrough", onLoad, true);
soundFile.addEventListener("error", onError, true);
}
function onResourceLoad() {
if(resourcesLoading == 0)
onLoaded();
}
It's hard to diagnose the problem because it shows no errors and only fails occasionally.
I got it working. The solution was fairly simple actually:
Basically, it works like this:
channel.load();
channel.volume = 0.00000001;
channel.play();
If it isn't obvious, the load function tells browsers and devices that support it to start loading, and then the sound immediately tries to play with the volume virtually at zero. So, if the load function isn't enough, the fact that the sound 'needs' to be played is enough to trigger a load on all the devices I tested.
The load function may actually be redundant now, but based off the inconsistiency with audio implementation, it probably doesn't hurt to have it.
Edit: After testing this on Opera, Safari, Firefox, and Chrome, it looks like setting the volume to 0 will still preload the resource.
canplaythrough fires when enough data has buffered that it probably could play non-stop to the end if you started playing on that event. The HTML Audio element is designed for streaming, so the file may not have completely finished downloading by the time this event fires.
Contrast this to images which only fire their event once they are completely downloaded.
If you navigate away from the page and the audio has not finished completely downloading, the browser probably doesn't cache it at all. However, if it has finished completely downloading, it probably gets cached, which explains the behavior you've seen.
I'd recommend the HTML5 AppCache to make sure the images and audio are certainly cached.
The AppCache, as suggested above, might be your only solution to keep the audio cached from one browser-session to another (that's not what you asked for, right?). but keep in mind the limited amount of space, some browsers offer. Safari for instance allows the user to change this value in the settings but the default is 5MB - hardly enough to save a bunch of songs, especially if other websites that are frequented by your users use AppCache as well. Also IE <10 does not support AppCache.
Alright so I ran into the same problem recently, and my trick was to use a simple ajax request to load the file entirely once (which end into the cache), and then by loading the sound again directly from the cache and use the event binding canplaythrough.
Using Buzz.js as my HTML5 audio library, my code is basically something like that:
var self = this;
$.get(this.file_name+".mp3", function(data) {
self.sound = new buzz.sound(self.file_name, {formats: [ "mp3" ], preload: true});
self.sound.bind("error", function(e) {
console.log("Music Error: " + this.getErrorMessage());
});
self.sound.decreaseVolume(20);
self.sound.bind("canplaythrough",function(){ self.onSoundLoaded(self); });
});

Categories

Resources