I have Chrome Extension that consists of a popup and an Event page that runs in the background. The Event page is really simple: it registers an onMessage listener and when that listener is called, it creates an Audio object with a remote .mp3 file as the source and plays it. When the Event page gets another message and audio is playing, it pauses the audio and stops the play back.
var audio;
chrome.runtime.onMessage.addListener( function(message, sender, sendResponse) {
if (audio && !audio.paused) {
audio.pause();
audio.src = '';
audio.load();
audio = null;
sendResponse({});
} else {
audio = new Audio("http://path/to/audio/file.mp3");
audio.play();
sendResponse({});
}
});
The popup jump simply sends a message to the Event page to start playing the audio. The audio plays fine and stops playing when the Event page receives the second message, but the issue is that when the Event page receives the second message, pauses, and sets the audio source to an empty String, the Event page never goes away. It will persist in the background like a Background page and never goes into it's inactive state.
I tried creating the audio var like this to see if using the Audio constructor was causing the issue:
audio = document.createElement('audio');
But that did not behave any different. I then tried setting the preload attribute to none instead of auto to no avail. I am wondering if Chrome is opening a socket to load the mp3 file and is not closing it properly, so the Event page still thinks that it is active because of the open socket, but that is just speculation at this point...
Is there something else that I need to do to "unload" the audio so that the Event page will go into an inactive state when audio is not playing?
After upgrading Chrome to version 36, the Event page goes inactive after the Audio element is unloaded.
Related
I've got an issue with my app and I could reproduce it on this sample: https://webrtc.github.io/samples/src/content/getusermedia/record/
During a phone call, if I open a tab with a video with audio element, the video automatically pause (and can see a pause event on the element)
This does not happen if the video element was loaded and played before the phone call start, or if the video has no audio.
Is this a normal behaviour, and can it be tracked (by an event other than the pause one) ? Is there any way to know there is a phone call ongoing, or any way to restart the video during the phone call (element.play() works, but a pause event immediately happens) ?
To reproduce:
On a mobile (iOS or Android)
Start a phone call
Open https://webrtc.github.io/samples/src/content/getusermedia/record/
The video is paused
If you manually launch element.play(), you can see the frame in the video updating, and then pause again
The record works correctly
what (likely) happens is that the video element (which needs to synchronize audio and video) is waiting for audio data but doesn't get any from the underlying layers when a phone call is active.
A possible workaround would be to change how you display audio and video, each in their own elements with MediaStream as srcObject that only have the respective audio and video track of the original stream.
Can you file a specification issue on https://github.com/w3c/mediacapture-main/ please? This is a rather interesting case that warrants some discussion.
I have Audio file playing in jQuery. sometimes when the download speed is slower than the playing speed, audio can stop. I want to get a notification when this situation is happening and so for example the music stops and I get the console error every minute, then once the buffer is loaded enough to play the song then it stops sending the notification. In reality there will be a loading icon that appears and disapears. So i need both inititing event and stopping event.
This is the events I tried to have but I do not get the right results.
the list of events are here: link
$(audio).on("canplay, playing, ", function () {
console.log("stop Buffering");
});
$(audio).on("buffered", function () {
console.log("buffering");
})
buffered is a property of audio element, not an event. You should be listening to waiting event.
The waiting event occurs when the video stops because it needs to
buffer the next frame. This event can also be used on
elements, but it is mostly used for videos.
w3schools.com/tags/av_event_waiting.asp
I have this in the window load listener function.
var audio = new Audio();
audio.src = "assets/silence.mp3";
audio.load();
document.getElementById("body").addEventListener(
'touchstart',
function(evt){ audio.play(); audio = 0; },
{capture:false,once:true,passive:true}
);
In chrome on android (with remote debugging open), I touch the screen and it (correctly) triggers trying to play the audio. However, it fails and logs this to the console:
(index):65 Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first.
How else am I supposed to trigger audio in a way that ensures the user initiates it, if not through a user interaction event listener?
aha. turns out, touchstart doesn't count as a "user interaction" from the perspective of the mechanisms preventing auto-play.
solution: swap it with click.
one thing I'm still frustrated with:
I'm using this specific snippet as a means of very quickly allowing audio to be played on the page so that the underlying html5 game can play audio without worrying about it being blocked by the browser.
however- because it needs to wait for a full "click" event (as opposed to a "touchstart" event), any audio that should be triggered on "touchstart" is going to be passed over (for the first time it would otherwise be triggered).
it seems like 1. there's no way to get around this to use it how I'd like, and 2. if you're able to just listen to the whole document for a "click" anyways, it's not actually doing anything from stopping unwanted audio.
If anyone can come up with a better solution, I'll swap the "correct answer" to that.
I had the same problem when I was making a web piano. The browser charged the piano on load, so you could press(actually touch the screen) the piano keys before you click something. What I did was to add a starting screen with a button to start the game and this solved it because you had to click something before you touch the piano keys.
I am creating a client-side SoundCloud application and I want to be able to play the next SC widget (iframe object) after the previous widget hits the .FINISH event (referred to in their api https://developers.soundcloud.com/docs/api/html5-widget#methods). When the page is in focus, it works properly and plays the next track; however, when I play a song and go to another tab, the next song doesn't start playing until I focus that tab again. I am using Chrome right now and haven't tried any other web browsers.
Any thoughts?
I tested the play() on SC.Widget.Events.READY while the page is in an inactive tab. I made my page title change when the event READY is triggered, it worked. The play() did too, but the effect of it was "paused" until that inactive tab became active again. I did more extensive test with play(), setIntervals and song in progress. It was properly fireing on inactive tabs while song was in progress but never on READY events while inactive tabs. Sorry I can't help you with a solution, I haven't found one yet, hopefully this will guide you through one.
var widgetIframe = document.getElementById("YourPlayer"),
widget = SC.Widget(widgetIframe);
widget.bind(SC.Widget.Events.READY, function() {
document.title = "test";
// widget.play();
});
EDIT: I queued a YouTube iframe after a soundcloud iframe with autoplay using YouTube API. It did exactly the same behavior, it will only start playing if the tab is on active. The more I dig the more I belive it is related to iframe and/or how browser works.
I want to be able to pause a video when the user clicks on an href that links to a third party web site and start it again when focus returns. I have searched for events but am unable to find one that works eg onunload onchange. I have an event handler that starts a new video when one stops and scrolls down the page (javascript) but I am stuck on this problem. I tried an href that called a javascript function but it became messy (the href is generated dynamically).
window.addEventListener('focus', function() {
document.title = 'focused';
});
window.addEventListener('blur', function() {
document.title = 'not focused';
});
You can use this code to get focus and blue event for window tab and call your play and pause functions from here.
If the third party link opens in the same tab (as opposed to a new tab or popup window) you won't be able to just pick up where you left off until you save it.
You could potentially store current state data on the client using html5 web storage. You would want to fire this on the window.onbeforeunload event. When they return just check for any stored data to resume playback with. This obviously isn't supported on all browsers yet. If saving server side is an option you could do that as well.
web storage spec from w3 here
web storage currently supported by browsers here
If, however, the page never unloads, it just loses focus, you could just add a listener on the page's html to trigger pause on the blur event. Resume on focus.