I am attempting to get a webpage to play a short notification sound whenever an icon changes colour. Using HTML5 this is the very simple matter of:
audio.play('ping.mp3');
...however, I need IE8 compatibility and audio.play() obviously causes an error whenever running in IE8 since the browser does not support HTML5.
I can live without the sound playing for IE8 users as there will still be a visible indication on screen, I just need to IE8-proof the code such that it doesnt throw an error and stop the script.
Try to check first if you can create the element. If yes, then it means audio tags are supported and then you can proceed with your code playing the audio
var hasAudioSupport = !!(document.createElement('audio').canPlayType);
Related
I'm recording audio using getUserMedia, then allowing the user to click a button to listen to either the recording or another buffer. This has all worked fine for a year, so I don't think I'm violating any of the rules that cause AudioContext to be suspended. And, anyway, I'm testing the AudioContext to make sure it isn't suspended in my button handler.
This has all been working fine on all modern systems with many browsers. However, this is not playing the audio in Safari 13 in iOS. It will return from the promises as if it were playing audio, but nothing sounds until I call getUserMedia again.
As an experiment, I put the following line on the top of my button handler:
navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: {ideal: false},
}
});
And it works!
But, why? I'm not comfortable with that solution because I'm not sure why the browser wants that. It doesn't make sense to me that I'd have to request the microphone to play any sound.
The only clue I have is that once I do the getUserMedia I keep the recording open on Safari (I do that because Safari has a time out - when I request the mic, it pops up a dialog to the user to allow the mic. Sometimes it might take the user 90 seconds to get around to pressing "record", and if I don't leave the mic open it pops up the dialog again.)
Anyone have any idea what is going on? And, I haven't been able to find any technical write up of Safari and audio. Is there anything beyond the standard MDN?
IOS13 also broke one of our applications. It's been working fine for years. No errors are thrown and we are not violating any rules. Here is the link to my post:
Has IOS13 broken <audio> tags used as audio buffers connected to the audio context?
Even though it is a different use of the api, I believe it is related. Apple clearly broke something on this new release.
This was confirmed to be a bug in Safari 13 and was fixed in a maintenance release. We haven't heard any more reports from the field so I guess it auto updated for everyone.
I'm trying to play a sound over itself on keydown.
In order to do so, I saw the solution is to clone the sound and play the new instance instead:
var promise = sound.cloneNode(true).play();
Reproduction online:
https://jsfiddle.net/alvarotrigo/up4c6m95/13/
This seems to be working fine in Chrome and Firefox. However in Safari this results in bad performance.
Try typing very fast with both hands to reproduce the error.
Note I added a gif image that lags when typing very quickly.
This can of course be noted as well on the Safari dev tools as can be seen in the picture below:
Whole code here:
var sound = new Audio('https://www.w3schools.com/html/horse.mp3');
document.addEventListener('keydown', playSound);
function playSound() {
//in order to play the same sound over itself
var promise = sound.cloneNode(true).play();
//we just dont want to show the console error when autoplay is disabled :)
if (typeof promise !== undefined) {
promise.then(function() {
// Autoplay started!
}).catch(function(error) {
//error
});
}
}
Safari puts a request every time for the audio file being played, while on the other hand it's not the case for Firefox and Chrome as they tend to load it only once.
In Safari on iOS (for all devices, including iPad) ... no data is loaded until the user initiates it.
This means the JavaScript play() and load() methods are also inactive
until the user initiates playback, unless the play() or load() method
is triggered by user action.
I don't think you can get around the slow performance resulting in putting out a request on each keydown.
I'm trying to do a simple thing. I want some audio to play exactly after 10 seconds when the user enters the webpage. I used the following code
var aud=new Audio("someAudio.mp3");
$(document).ready(function(){
setTimeout(function(){aud.play()}, 10000);
});
It is working perfectly fine on desktop browsers. However, the audio is not playing in some mobile browsers like Google Chrome though it is working in Firefox. What may be the possible reason for this and how to fix it? I saw some similar questions but didn't find a suitable answer.
Thanks in advance
I'm trying to do a simple thing. I want some audio to play exactly after 10 seconds when the user enters the webpage.
You can't unless there has been user interaction.
Handle a click event for some element. In that event handler, play some other audio. (This audio can be silent!) After 10 seconds have passed from load, if the user has touched/clicked something, and you've done this, you should be able to play your audio file.
I'm trying to add a callback to a HTML5 audio element on an iPad.
I added an eventlistener to the element, the myOtherThing() starts but there is no sound. If I pause and the play the sound again the audio starts. This works in Chrome. Does anyone have an idea how I can do this?
myAudioElement.src = "path_to_file";
addEventListener("canplay", function(){
myAudioElement.play();
myOtherThing.start();
});
SOLVED
Just wanted to share my solution here, just in case someone else needs it. As far as I understand the iPad does not trigger any events without user interactions. So to be able to use "canply", "playing" and all the other events you need to use the built in media controller. Once you press play in that controller, the events gets triggered. After that you can use your custom interface.
You need to tell Safari to begin loading the file. Plus, the canplay event isn't supported on iOS. Just call play immediately after calling load.
myAudioElement.src = "path_to_file";
myAudioElement.load(); // Start loading the audio
myAudioElement.play();
I've been evaluating HTML5 audio on iOS 4 and have been trying to understand its limitations. From what I can tell...
It is possible to play audio in the background
It is not possible to fire JavaScript events in the background upon track completion
It is possible to fire JavaScript events while the screen is off, but Safari must be in the foreground (before turning the screen off)
My goal for this current project is to create a dynamic playlist that will continue to fire events and move to the next track even while Safari is not in the foreground. Is this possible with the current way HTML5 audio works on iOS?
I am curious about how the chaining of JavaScript events works on iOS if anyone has additional information. It seems that you are allowed to queue back to back sounds, but it must happen shortly after a "human" function happens (for example, tapping an element). Anything else that tries to queue a sound outside of this human function is denied the ability to play.
Also...
Is it even possible to have events that fire to move a real iOS application to the next track? It seems as if the application is only allowed to finish its current audio stream and then it goes into an idle state. Just trying to figure out all the angles here!
This is quite an old question, so I'm not sure if you've found an answer already or not.
One thing I know is that an audio clip cannot be played via JavaScript on mobile Safari.
Autoplay audio files on an iPad with HTML5
The only way to make audio play, is through a click event. This wasn't the case on 3.x, but on 4.x it is. This is because Apple doesn't want the webapp to download audio on a 3g connection programmatically, so they force the user to initiate it.
I would think that if all of the tracks were started downloading (cached), then it may be possible. I would try forcing the user to start one track, and at the same time call .load() on all of the other tracks (in the same click handler). This will force the iOS device to start downloading the audio tracks, and you may be able to play the next track (not sure though).