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.
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
I'm trying to fast-forward a video playlist on a website to unlock access to the next one. Videos stream without the possibility of fast-forwarding, forwarding and I haven't any video control bar. I have to wait that they slowly finish. When I refresh the page, the video starts on the minute I've left it before. This is the relevant HTML code.
Looking at the video events I've found that it is an open source code of streaming videos, this is the whole relevant code I've copied from Firefox Debugger (with various events).
This is what I've tried on Firefox console to skip the video:
var video = videojs(document.querySelector("video"));
video.currentTime(video.duration());
but it just doesn't work (it reloads the page to the same video, basically it doesn't unlock the next one).
I've also tried to speed up the video with the following code:
document.querySelector("video").playbackRate = 2;
it speeds up but after a second the video gets stopped, and when I refresh the page the time I was at with the speed-up doesn't get saved.
How can I effectively fast-forward/skip it? I have no idea why this is happening.
The site you are accessing is an online learning platform and they will have built in controls to try to avoid people skipping ahead - this is fairly standard with online learning.
There are multiple ways they could do this for example:
report progress regularly from the browser and if it is too fast, reset video back to an earlier point.
monitor requests server side and again if the requests indicate too fast movement through the video, reset the client or respond to the requests with earlier video.
You can study the network traffic and you may be able to find a way round their mechanisms. This might even be arguably a useful use of your time if you are studying Javascript or video, although the tutors probably won't see it that way, but it may be tricky if they have multiple checks built in. You may also miss a mechanism which flags your activity on your account in the background to the tutors which might not be something you want happening...
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.
Alright, I'm working on one project which involves html5 audio, in addition to that a video is shown while audio is playing (Just video, no controls etc). Video is a visualisation (sometimes called equaliser) of audio that is playing, made beforehand in adobe after effects. both files (video and audio) are same length e.g. 3 min 20 sec. I need a way to synchronise both, as video might load slower than audio or vice versa. Therefore I need to make it so that on computers with slow internet connection if video stops loading at some point and starts buffering I need to pause audio, and once video resumes start audio again, both at exactly same time, also when user skips to a certain bit in a song, video should skip to that bit as well, I'll use custom api made player for video so there would be no controls on video, only on soundcloud player.
It is almost as if I was using soundcloud custom player to control video. I'm struggling to find any resources on this anywhere, and would really like to know how to achieve this functionality.
javascript or jQuery solutions are preferable.
What makes it even more complicated is that I use SoundCloud's custom player to play songs:
http://developers.soundcloud.com/docs/custom-player#
And upload videos to Vimeo/YouTube (all done to decrease load on a website)
Check here: http://html5demos.com/two-videos
The sample is for syncing 2 videos, but with some hacking probably you can manage to sync audio and video.
Second, don't use Custom player, make your own HTML5 Audio element, check the SoundCloud API there is a property stream_url for every streamable track on soundcloud, just put that URL as source on your html5 audio tag.
Keep on mind that this will not work on Firefox and Opera for some time. Firefox will integrate native mp3 support in v20, not sure about opera
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).