HTML sound doesn't play at times when browser tab not focused - javascript

This is pretty insane. I've built a VueJS based frontend for an order recieving application. Technically I'm making an ajax call every two minutes to check for orders. If there are any orders I have it play a sound. This I've implemented by calling play on an hTML audio element.
The problem is that if the browser tab is not focused or if the user is on another tab. The sound doesn't play. I've even changed the code to instead of playing a sound file - refresh a hidden iframe that loaded the sound file. But that also doesn't seem to work if the browser is out of focus. What exactly am I missing here.
-- EDIT
My situation is that - the user would have multiple browser tabs open and the only way to alert the user would be via a unique sound that would be played. I know it can be done because there are a number of other sites that do this somehow. I'm not sure how. Is there a way to force focus back to the tab using javascript?

Related

Javascript: Play Sound in Browser: Persist somehow that a user interacted with this page?

current browsers disallow JS to play a sound unless the user interacted with the page first. See
https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
I do have a page which visualizes the CO2 value of a sensor, and if the value is too high, it should play an alarm sound using JS. For doin so, there is a button which toggles sound on/off.
When the user interacts with the page, JS is allowed to play the sound.
But when exactly the same URL is reloaded (on the very same machine), the user has to interact again with the page to allow JS to play the sound. I would somehow like to be able to persist the state that the user interacted with this particular URL already, so I can play the warning sound when the same URL is reloaded and the user selected before that the sound should play. Is there a way to do this?
To give you a better impression, here are 2 Screenshots with warning sound turned on/off by the user. I would like to persist this selection (no problem using localStorage), but Chrome disallows playing the sound after reloadinf the page unless the user interacts again. I would like to be allowed to play that sound after a page reload.
Thanks & bests regards
Philipp

Showing audio metadata on phone block screen?

I have an html5 audio player on my page that streams from my icecast server, all working OK. However, when people block their phone there's no metadata, only the play button that iOS/Android offers.
Is there a way to show something like 'Glaciar's livestream', like when the Spotify app shows the song's title and artist? I'm using PHP and Javascript apart from HTML and CSS.
Thanks in advance!
You can use the Media Session API to customize what's been shown on the lock screen.
But it is not supported by Safari which means you can't use it to customize the lock screen on an iOS device.
I just came along the same issue. Our Webapp would not display anything on the lock screen even though audio was playing. This is what I just found out:
We are setting up an new Audio() element in javascript - within the user interaction we call audio.load(). Then we wait for the canplay event to fire and with that event handler, we call audio.play(). When the phone now gets locked, there is nothing shown on the lock screen.
However, when we add audio.play() directly after audio.load(), so it is called within the same user interaction, everything shows up fine on the lock screen. So it seems like, it matters if audio.play() is called within a user interaction.
Some more background in case someone wonders why we are not calling play within the user interaction: We usually use an audio context (that is unlocked within a user interaction) and just started to fall back to an audio element, due to numerous audio related bugs in safari.

How to properly handle switching html5 Videos

I have come here after much trouble with something that may be only related to videos, and Is likely a bad understanding of page resources in general. What I am trying to accomplish is the ability to have a single web page in which, by clicking 'forward' and 'back' buttons, one may change the contents of a div to display one of the videos in obvious sequential order. The video is currently in mp4 format in a html5 video element.
I have tried a few methods.
directly changing the src of the source element (does not seem to do anything)
remove the element, and re-add it with different src. (has problem described below)
remove the element, and use Jquery .load() to place an external html file with the entire video element in it, including a separate html file for each src. (has problem described below)
remove the element, and re-add it with a src pointing to a download of the file from GridFS using the python flask framework. (has problem described below)
Ok, so the main issue I am having is with repeat downloads of the same video from the page. Say if you click 'next video', then 'previous video'. This causes the video to be 'black' (not loaded at all, acts like src is broken). The first time each of the videos are requested, it loads in under a second, the second time varies but is always over 10 seconds. before the content of the video pops up and it becomes playable. Google chrome's dev network tools lists the media as 'pending' while I am waiting, when when it is done waiting finally it turns the above video to red (canceled) and the new source to 'partial content'. During the wait time, it can not seem to pull anything from the server including rollover images.
I have tried this locally with flask and python simple html server, as well as on an 8 core server over gigabit Ethernet. This is not an issue of random network latency, something weird is going on.
One of the things I am trying to figure out is how making a new request to the server works with partial content. I had some idea that the browser cache would store the file so that the second time loading it should be faster, which would be optimal anyway. Does this still happen with html5 videos?
Also of note, the files are fairly small, one minute or so videos of about 20 mb. It seems like the web server is just blocking the second request for some reason and I am wondering if any of you have ever heard of this. I can post code upon request but I think the concept is pretty much straightforward.
I plan to use GridFS with flask for the final implementation of this site.
Due to the below suggestion, I have tried doing away with the source element and having the src attribute attached onto the video itself. This produces the same result. Here is the fairly simple thing I am doing:
$('#addlinks').click(function(){
$('#maininside').remove();
$('#maintext').append('<div id=maininside></div>');
$('#maininside').html('<video width="100%" controls src="/getmedia/dangerisland-01-video-01.m4v">Your browser does not support the video tag.</video>');
});
<article id="maintext">
<div id="maininside">
</div>
</article>
The first time the button is clicked, there is a very slight delay and I can see high network usage in a monitor as the video is downloaded. Once the button is clicked again, I get no network usage for about 30 seconds in this case, then it downloads at full speed again and comes back up. Here is the dev view of network use right after it comes back up the second time:
Thank you for any insight you might have.
There are a lot of sub-questions and variables here; not sure how well I can address them all--but I'll give it a try.
The comment by kalhartt steers you correct in regard to simply
changing the source. But I'll note that in my experience the behavior
you'll see from the various browsers as you go through this process
will be inconsistent. I've done some work on this over the past year,
and at least at the time it was a poor user experience--the user experienced the video as broken while the browser responds to the change in source and new
load. We ended up generating new video elements and switching them out (but even this can be fraught with pitfalls due to differences in which media events each browser is publishing when.)
I'm not positive how you're serving the videos, but the flask
development server is blocking (unless you set
app.run(threaded=True), I think.)
It's also possible you're running
into behavior caused by the internal video loading/caching logic in
the browser, and you will even observe significant variation in how each
browser handles these tasks. A good way to test
against this behavior would be to append a unique query string
(perhaps with a timestamp) for each load; the videos should happily
load (if the server isn't blocking.) If server blocking is the issue it may be worth hosting the videos on S3 until you're ready to focus on how they're delivered.
Another possibility is not destroying the original video object if you suspect it's going to be used again (instead you can pause it, remove it from the DOM, and save a reference to it). If re-use is an unlikely case, though, and especially if you expect the users to play many videos on a single page load, it may be best to discard them. A compromise might be retaining a fixed number of previous video objects.

Play sound only in one window of which is active (within one website) using javascript (possibly jquery)

Alright, I've found a bunch of answers concerning native functions like window.onblur and window.onfocus... But they won't help so I'd like to be more specific
Say you open several tabs of one website
Say you receive a message and there's a sound to announce the message
As you have several tabs opened, you will hear the sound the number of opened tabs. Which makes a how'd'u'callit symphony
Best solutions I've found so far, but which don't work
1. window.onfocus and window.onblur
2. Play sound if var infocus evaluates to true, don't play if not
3. It is crossbrowser
4. It is simple
5. It does not work
Why the best solution won't work? Say you switch focus to another tab of a different website, your website loses focus so you won't hear the sound. Even worse, say you switch to another program, then the browser itsel loses focus and you won't hear the sound
So what shall I do?
You could save the timestamp of the last onFocus() event in a JavaScript variable and in a cookie (access set to your website root). Then when you want to play the alert sound, you compare the current values of the variable and the cookie and only play the sound if those two match.
Alright, two weeks after it seems like I've found the real solution. Which actually proves that if you want to do something, don't ask for help, just do it
This is what I did:
Create a cookie with a randon id and the current time (winid + t1). The cookie is created by each opened tab on loading.
document.cookie = 'winid='+winid+t1;
Create a function which will update the current time in the set cookie, say, every 3 seconds (I kindda don't like to overflow clients, so it's 3 secs not 1). If the function finds out that the winid in the cookie and the winid of the current tab don't match and 3 secs have elapsed, then the tab was closed, redefine the primary tab inside the same function.
window.setInterval(setwinid,3000);
This is it, every time you need to, say, play a sound, you should check first, whether it is the tab which is to play it
The trick is that each tab has its own winid. But only one winid is stored in cookie, is updated and thus allows the one tab to perform actions. Pretty simple. I actually started using this method for updating messages in the box across all tabs not only for playing music
One solution would be to have a server-side solution that would play the notification only once. You don't specify how the site receives the messages, but I assume it's some form of AJAX call that gets the message from the server and the messages are saved in a database.
Add a flag to the database that signifies that the message has been sent. Set the flag the first time the user's browser queries for new messages. On the page itself play the sound only if the flag has not been set, otherwise don't play the sound. Now only the first page that fetches the message will play the sound.

x-webkit-speech, how to auto click the mic icon to record many words automatically?

I am working on chrome browser. The code
<input x-webkit-speech> will show this:
if you click the mic icon, you can input speech. like this
My question is how to make it record voice to recognize automatically, without manually click the mic icon?
Such as when the page loaded, it start to record; or write codes to emulate a click event? Is it possible?
May you give a sample code or x-webkit-speech API's document?
Thank you.
This should not be possible, because if it were it would be a privacy hazard — a page could start recording what is said in the vicinity without the user being aware of it or intending to. If there is any way to accomplish this, it will most certainly be removed as soon as the browser developers become aware of the problem.

Categories

Resources