HTML5 Audio on an iPad/iPhone device stops when being touched - javascript

In order to get an HTML5 animation playing with sound on an idevice, I've made a div the size of the entire browser named "theScreen", and use the following code:
audioCont.prototype.iCrapLoadPlayThrough = function () {
if (this.supported) {
theScreen = document.getElementById("theScreen");
var self = this;
theScreen.addEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
return(1);
} else {
return(0); // Not supported
}
};
audioCont.prototype.iCrapClickedLoadPlayThrough = function () { // Check if supported, then load the audio file
var self = this;
theScreen.removeEventListener('touchstart', function(){self.iCrapClickedLoadPlayThrough();}, false);
this.addCanPlayThrough();
this.load();
}
Now this works, and the sound/animation starts when the user taps on the screen. The problem is, if they tap on it again the sound stops, and each repeat tap you hear a few ms of audio. Does anyone know why?

It's not removing the event listener because it's an anonymous function. Remove the anonymous function and just have the function name instead
theScreen.addEventListener('touchstart',self.iCrapClickedLoadPlayThrough,false)
theScreen.removeEventListener('touchstart',self.iCrapClickedLoadPlayThrough,true)

I've found a solution to the problem:
theScreen.addEventListener('touchstart', eventID=function() {self.iCrapClickedLoadPlayThrough();}, false);
then
theScreen.removeEventListener('touchstart', eventID, false);

Related

How to play sound in javascript?

I create websocket server in python to handle notification event. Now, i can receive notification, the problem is i can't play sound because new autoplay policy changed, if i play sound using javascript it give me domexception. Any suggestion please ?
As i know, playing sound is simple in html-javascript. like this example: https://stackoverflow.com/a/18628124/7514010
but it depend to your browsers and how you load and play, so issues is:
Some of browsers wait till user click something, then let you play it (Find a way for it)
In some case browsers never let you play till the address use SSL (means the HTTPS behind your url)
The loading be late so the playing be late / or even not start.
So i usually do this:
HTML
<audio id="notifysound" src="notify.mp3" autobuffer preload="auto" style="visibility:hidden;width:0px;height:0px;z-index:-1;"></audio>
JAVASCRIPT (Generally)
var theSound = document.getElementById("notifysound");
theSound.play();
And the most safe if i want sure it be played when i notify is :
JAVASCRIPT (In your case)
function notifyme(theTitle,theBody) {
theTitle=theTitle || 'Title';
theBody=theBody || "Hi. \nIt is notification!";
var theSound = document.getElementById("notifysound");
if ("Notification" in window && Notification) {
if (window.Notification.permission !== "granted") {
window.Notification.requestPermission().then((result) => {
if (result != 'denied') {
return notifyme(theTitle,theBody);
} else {
theSound.play();
}
});
} else {
theSound.play();
try {
var notification = new Notification(theTitle, {
icon: 'icon.png',
body: theBody
});
notification.onclick = function () {
window.focus();
};
}
catch(err) {
return;
}
}
} else {
theSound.play();
}
}
(and just hope it be played. because even possible to volume or some customization make it failed.)
to bypass new autoplay policy :
create a button that can play the sound, hide it and trigger the sound with :
var event = new Event('click');
playBtn.dispatchEvent(event);
EDIT
assuming you have :
let audioData = 'data:audio/wav;base64,..ᴅᴀᴛᴀ...'; // or the src path
you can use this function to trigger whenever you want without appending or create element to the DOM:
function playSound() {
let audioEl = document.createElement('audio');
audioEl.src = audioData;
let audioBtn = document.createElement('button');
audioBtn.addEventListener('click', () => audioEl.play(), false);
let event = new Event('click');
audioBtn.dispatchEvent(event);
}
usage :
just playSound()
EDIT 2
I re test my code and it does'nt work hum ... weird

safari ios audio- refusing to play with error

The javascript error is: Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
My setup works across other browsers, desktop and mobile.
The way it works is:
have a flag first_audio_played = false;
add a touch event listener that plays some audio, and sets first_audio_played = true; (then removes the touch listener)
all subsequent audio checks if(first_audio_played) some_other_audio.play();
this way, only the first audio played requires direct user input. after that, all audio is free to be triggered by in-game events, timing, etc...
this appears to be the "rule" for audio across most browsers. is the iOS "rule" that every audio needs to be triggered by user input? or is there some other step I'm missing?
For my javascript game, sounds stopped working on iOS recently. They all have readyState=4, but only the sound I played on tap works, the others won't play. Maybe you could play all the sounds on the first tap. But the solution I found that works for now for me is to load all the sounds from ajax arraybuffers and use decodeAudioData(). Then once you've played 1 sound from user tap (on not the body), they all play whenever.
Here is my working code where the second way of doing it is on bottom. When I tap to play sound2, sound1 starts working also.
<html>
<body>
<div id=all style='font-size:160%;background:#DDD' onclick="log('clicked');playSound(myAudio)">
Sound1 should be playing every couple seconds.
<br />Tap here to play sound1.
</div>
<div id=debug style='font-size:120%;' onclick="playSound(myAudio2)">
Tap here to play the sound2.
</div>
<script>
var url = "http://curtastic.com/drum.wav"
var url2 = "http://curtastic.com/gold.wav"
var myAudio, myAudio2
if(0)
{
var playSound = function(sound)
{
log("playSound() readyState="+sound.readyState)
log("gold readyState="+myAudio2.readyState)
sound.play()
}
var loadSound = function(url, callback)
{
var audio = new Audio(url)
audio.addEventListener('canplaythrough', function()
{
log('canplaythrough');
if(callback)
callback()
}, false)
audio.load()
if(audio.readyState > 3)
{
log('audio.readyState > 3');
if(callback)
callback()
}
return audio
}
myAudio = loadSound(url, startInterval)
myAudio2 = loadSound(url2)
}
else
{
var playSound = function(sound)
{
log("playSound()")
var source = audioContext.createBufferSource()
if(source)
{
source.buffer = sound
if(!source.start)
source.start = source.noteOn
if(source.start)
{
var gain = audioContext.createGain()
source.connect(gain)
gain.connect(audioContext.destination)
source.start()
}
}
}
var loadSound = function(url, callback)
{
log("start loading sound "+url)
var ajax = new XMLHttpRequest()
ajax.open("GET", url, true)
ajax.responseType = "arraybuffer"
ajax.onload = function()
{
audioContext.decodeAudioData(
ajax.response,
function(buffer)
{
log("loaded sound "+url)
log(buffer)
callback(buffer)
},
function(error)
{
log(error)
}
)
}
ajax.send()
}
var AudioContext = window.AudioContext || window.webkitAudioContext
var audioContext = new AudioContext()
loadSound(url, function(r) {myAudio = r; startInterval()})
loadSound(url2, function(r) {myAudio2 = r})
}
function startInterval()
{
log("startInterval()")
setInterval(function()
{
playSound(myAudio)
}, 2000)
}
function log(m)
{
console.log(m)
debug.innerHTML += m+"<br />"
}
</script>
</body>
</html>
You can use either [WKWebViewConfiguration setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeNone] or [UIWebView setMediaPlaybackRequiresUserAction:NO] depending on your WebView class (or Swift equivalent).

Fire function when HTML5 video seeks/plays

I am trying to stream video using links that expire every 2 minutes.
Basically, I use this function to replace the URL, and it works great:
function test(){
var videoFile = 'new.mp4';
var $video = $('#m video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
}
The question I have is how do I fire this function every time the video starts playing/after someone seeks in it? If i fire the ok(); function using a play event then it starts a loop since the function itself causes a play event.
Does anyone have any ideas on how to fix this in a good way?
The solution would be to register the play event once the video has actually started playing. That way it will react after a pause or a seek.
If you need to disable the event on other conditions then you simply disable the play event (as done in the start of the playing function)...
function test(){
var videoFile = 'trailer.mp4';
var $video = $('#video');
var curtime = $video[0].currentTime;
videoSrc = $('source', $video).attr('src', videoFile);
$video[0].load();
$video[0].currentTime = (curtime);
$video[0].play();
$video.on('playing', function () {
$video.off('play') // remove existing Play event if there is one
console.log("Play event bound")
$video.on('play', function () {
console.log("Video play. Current time of videoplay: " + $video[0].currentTime );
});
});
}

Flash HTML5 canvas conditions for audio.pause and resume function

Despite my readings I'm still limited in javascipt / soundJS syntax with using flash html5 canvas. I would like to pause and resume my sound with mouseover and mouseout events on the same button. I mean:
You hover the button: the music starts.
You mouseout: the music pauses.
You hover it again: it resumes from the position it has been paused with precedence.
According to the SoundInstance Class doc, you can do that with
myInstance.pause(); and myInstance.resume(); methods. And I suppose "var sound;" behaves likes "myInstance" since sound.pause(); works.
With the js code below I can pause the sound and resume my sound, but not on the same button, I need a button_2 to do that.
I think I'm missing a condition in mouseover function to "check if the sound is paused or not and then resume it or start playing.
var sound;
function fl_MouseOverHandler(){
sound = playSound("monstres");
}
this.mybutton.addEventListener("mouseover", fl_MouseOverHandler);
function fl_MouseOutHandler() {
sound.pause();
}
this.mybutton.addEventListener("mouseout", fl_MouseOutHandler);
function fl_MouseOverHandler_2(){
sound.resume();
}
this.mybutton_2.addEventListener("mouseover", fl_MouseOverHandler_2);
Any hint or link is welcome. Thank you.
what about something like this?
var isPlaying = false;
function togglePlayback(){
if(isPlaying){
isPlaying = false;
sound.pause();
} else {
isPlaying = true;
sound.resume();
}
}
this.some_button.addEventListener("some_event", togglePlayback );
You are an angel sent to earth.
Meanwhile I've found dome docs on javascript and managed to code my beloved function with something in the same spirit using a boolean variable.
Here's my code:
var playing = new Boolean(false);
function fl_MouseOverHandler() {
if (playing == false) {
exportRoot.soundInstance = playSound("monstres");
playing = true;
exportRoot.soundInstance.on("complete", handleComplete);
function handleLoop(event) {
exportRoot.soundInstance = playSound("monstres");
}
} else {
exportRoot.soundInstance.resume();
}
}
this.bout_zone_son.addEventListener("mouseover", fl_MouseOverHandler);
function fl_MouseOutHandler() {
exportRoot.soundInstance.pause();
}
this.bout_zone_son.addEventListener("mouseout", fl_MouseOutHandler);
I can't use if (playing) {....} syntax because:
i must first fire the sound with my button and then check if it's palying or not to resume it or start it.
I think I can't type sound.pause without first instanciating "sound = playSound("mylinkedsoundfromlibrary"); or my case exportRoot.soundInstance = playSound("monstres");
Well, thanx anyway for giving a shot in the right direction.

Windows 8 Audio playing in background

I have read previous posts on this and documents by microsoft but cannot seem to get my app to run Sound in the background. It plays 100% but when ever the app is then suspended the music also stops. I have added "Background Tasks" declarations selecting Audio and my audio tag looks like this
<audio id="musicplayr" msAudioCategory="BackgroundCapableMedia" controls="controls"><source src="song.mp3"/> </audio
and finally my javascript includes the references to MediaControls
var MediaControls = Windows.Media.MediaControl;
// Add event listeners for the buttons
MediaControls.addEventListener("playpressed", play, false);
MediaControls.addEventListener("pausepressed", pause, false);
MediaControls.addEventListener("playpausetogglepressed", playpausetoggle, false);
// Add event listeners for the audio element
document.getElementById("musicplayr").addEventListener("playing", playing, false);
document.getElementById("musicplayr").addEventListener("paused", paused, false);
document.getElementById("musicplayr").addEventListener("ended", ended, false);
and below in the code i have the event handlers
// Define functions that will be the event handlers
function play() {
document.getElementById("musicplayr").play();
}
function pause() {
document.getElementById("musicplayr").pause();
}
function playpausetoggle() {
if(MediaControls.isPlaying === true) {
document.getElementById("musicplayr").pause();
} else {
document.getElementById("musicplayr").play();
}
}
function playing() {
Windows.Media.MediaControl.isPlaying = true;
}
function paused() {
Windows.Media.MediaControl.isPlaying = false;
}
function ended() {
Windows.Media.MediaControl.isPlaying = false;
}
*Note musicplayr is the reference for the html5 tag
Any help appreciated why this is not working?
You also need an event handler for the stoppressed event. Without any of the four handlers--playpressed, pausepressed, playpausetogglepressed, and stoppressed--background audio won't be enabled. See http://social.msdn.microsoft.com/Forums/en-IN/winappswithhtml5/thread/2ca0c122-df31-401c-a444-2149dd3e8d68 on the MSDN forums where the same problem was raised.
.Kraig

Categories