How can I implement a continuous background sound in page that doesn't interrupt when the user moves from one page to another without using iframe?
use a trick, if having frameset is not an issue for you, construct your page with a frameset and use one frame for background (no size) where you play the sound and other (full 100%x100%) where you can navidate. This has also the advantage of hidding your navigation URL leaving just the site url on nav bar.
If you are insane, you could set an event listener on the timeupdate event of the <audio> element and store the currentTime in localStorage (or a cookie). Then, when you load a page, read that value and set the currentTime again. However, I imagine writing to localStorage dozens of times per second might be bad (but I won't make any performance claims until I test it!).
However, this solution requires a mordern browser with audio and localStorage support.
Related
I would like to have a web page being able to act like a music player.
The user enqueues a list of audio files (hosted on the server) and they start playing. When the first audio is over, the second begins, etc, until the last one.
I was able to easily implement this functionality using an <AUDIO> element, and replacing its src attribute with Javascript by adding an event listener on the ended event.
The problem is that this does not work consistently on mobile, because once the screen is locked, the Javascript does not keep executing. It may work for one song or two, but at some point it stops "skipping" to the next audio track.
From my understanding, this behaviour is caused by the fact that mobile browsers stop the Javascript event loop after some time to save battery when the screen is locked. I am aware of the Screen Lock API, I assume keeping the screen always on would solve my problem, but I don't want to keep the screen always on.
I could delegate playing audio files to a web worker, which should theoretically keep running in the background. Still, I'm not sure it won't be stopped when the screen is locked, and most importantly I am not sure it can even play sounds.
Is there anything similar to the Screen Lock API that allows me to ask permission to keep scripts executing also when the screen is locked?
If not so, how could I overcome this problem?
After some research, I discovered that the act of killing the javascript event loop is highly browser-specific.
Chrome for Android seem to let the playback run indefintely.
Firefox for Android is stricter, and kills the event loop.
The System Wake Lock looks like a promising API for solving the above problem. At the moment, the W3C is still in process of collecting use cases in order to be able to define a new standard:
https://github.com/w3c/system-wake-lock/issues/4
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?
Context
I am trying to loop several HTML5 videos one after the other. This is achieved via Javascript with an event listener listening for 'ended' - the video to end. At which point the url to the video is changed and video.play() is executed for the new URL.
For simplicity, lets say there are 2 videos that are to be (auto) played. After the second video finishes playing, it goes back to the first and plays that one (and the cycle continues). The videos will get cached on the user's device after they are first played.
TL-DR: Now what I want to achieve is to code a HTML5 video to be 'mobile friendly', in respect to mobile data plans.
I want the video to either stream when the page loads or buffer only a few seconds from after the point from where the user is watching. So if the user is 5 seconds into the video, the buffer extends to 15 seconds into the video (so 10 seconds of the video is buffered in case the network connection is weak). If the user pauses the video, the video stops buffering. Though the user won't have access to controls; they will be unable to forward, rewind or pause. I only gave the example of the user changing the point of the video to emphasise that I want control over how much the video has buffered and will buffer.
Alternatively, I want the video to stream to the user’s device. And only download that which needs to be immediately played. This is the less desirable option and is probably less desirable than leaving the video tag as it is since if the user has a dodgy connection, the video will play, stop, play, etc.
The reason for me wanting to achieve this is that I have noticed in Edge, IE, Firefox and Chrome that the video auto plays (good, that's what I want it to do) and plays while simultaneously downloading the whole video to their device (terrible). Of course this behaviour is expected, but practically, it should not do this. If users leave the site straight away, why would we want them to download a whole video they won't see?
Sort of but not entirely relevant, it doesn’t help:
HTML5 Video: Force abort of buffering
Simply put, the thread shows only hacks to hide the src and not any actual control over the buffer. I need to control the loading of the buffer in real time, relative to at what point the user is at, and not based on a 'pause' event. I would also like to know if there is a little-known supported method across most browsers (I only really need to worry about this on mobile) to achieve this, as opposed to a 'hack'.
Nevershowmyface: From what I can gather from the code, it stops the buffering every 0.5 seconds. There is no code for resuming the video? As for why this method will not work, it is not buffering relative to at what point the user is at. For all intents and purposes, it is still buffering the video in a linear fashion, without depending on a variable (the point at which the user is at). It's just doing it more slowly or 'in chunks'. If it loads another chunk just before the video runs out of video, I risk the video stopping and waiting to load again if the connection is poor.
Preload:none is useless here since the video is automatically played (notice bold auto at the top). I should have been more explicit. When the page loads, the video automatically plays. Preload loads the video before the play button is clicked on; preload:"none" does not load the video before play is clicked. But since there is no play button and the video plays once the page has loaded, it is a useless attribute.
My hopeless conclusion in regards to what should be a vital and basic feature
(not a rant)
From what I have found, there is no standardised way to achieve this and there are only ‘hacks’, as described in the post, which only serve to provide limited buffering functionality/ control in some browsers, potentially breaking other browsers and potentially having no effect in other browsers. In light of this, I’m on the verge of giving up on this task so thought I’d ask if anyone else has effectively managed to achieve this; it appears to have no support or has not even be considered in HTML5 or Javascript; I might be and hope I'm wrong – would be great to have this in Javascript.
Do other web developers not consider this when they use videos on their sites? I have spoken to other developers about this and they said the data usage from a site is not or is rarely the concern of the developer.
While I understand there are more important things to worry about, it goes without saying this would be very important for mobile users with low data plans.
Analysis:
The HTML5 audio element does not have a stop() function, nor does it
have an option where you can set the amount of data that it is allowed
to buffer, or a way of saying you want the element to stop buffering -
Don't confuse this with the 'preload' function, this only applies to
the element before the play button is clicked.
I have no clue why this is and why this functionality is not
available. If anyone can explain to me why these crucial functions are
not implemented in a standard that should make web development for
mobile phones better and more standardized I would love to know.
And before someone says the conclusion from that post was that this is currently impossible, note:
1) I am dealing with a video file, not an audio file. Slightly different context, where the file being buffered is significantly larger than an .mp3 file.
2) I am not trying to stop buffering altogether. I am trying to restrict it and keep it relative to the point of the video at which the user is at. So you could actually say I am trying to stop it but at an 'x' number of times after the point where the user's video is.
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.
We have a problem with IE. On a web page with a form, multiple frames are created via javascript. This is due to some crappy WYSIWYG. The problem is that when the user clicks on the browser "back" button, you'd expect the entire page to go back. This is what happens in FF, Chrome, Opera, Safari, etc. But for IE, you have to click the back button for each frame on the page, even if you don't do anything else but load the page.
Knowing that sometimes +20 frames can be on the same page (many textfields), this is a real pain for users.
The question: how do you make the browser back button work for the main page, regardless of the amount of frames you have on the page ?
Thanks so much !
One way of doing it is to implement clientside routing using hash bang urls.
Every time a page is changed on an iframe the hash part of the parent url is changed to reflect it.
You then have some js that listens for these changes and does what is needed to updated the full page state across frames.
Now when the user pushes the back button, the parents url changes to the hash it was before the last change in the child iframe, and everything is updated accordingly.
Be aware: that this is a non-trivial thing to implement if you have many iframes, and i can't give you a working script that will fix your problem. This is meant for inspiration only.
(following Martin Jespersen response)
Yes, I also thinks that it is only solution. And it is hard to implement, but there is a lot of good libraries to handle # changes.
The lightweight jQuery solution: http://tkyk.github.com/jquery-history-plugin/.
Very complex solution with ExtJS: http://dev.sencha.com/deploy/dev/examples/history/history.html#tab1:subtab1.
And I think, that is not possible to do it realibly cross-browser without javascript.