How to properly handle switching html5 Videos - javascript

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.

Related

Video doesn't effectively get its `playbackRate` or current time position changed

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...

How to control how much of a HTML5 video buffers?

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.

How not to overwhelm "Resources" or Memory Space in Browser?

I built a website using HTML/JavaScript that successively loads a total of 300 short videos. I've found, however, that some computers can't handle that much in their browser -- Is there a way to have my code avoid filling up the browser Resources with these videos? Also, is "Resources" (as defined in Safari 7) the same as Memory Space?
Thanks!
I would recommend loading the video thumbnails first, and when a User clicks one to then replace the thumbnail with the video. This would reduce the cost of loading up the page, since not all of the videos are loading up at once, unless you intend on all of them to play simultaneously.

Mobile Safari - are there limits in place to prevent large data consumption on first page load?

I have a webapp, that when loaded for the first time has a long initialization sequence. Basically it calls an external API to get loads of data which it caches upon completion, using HTML5 localstorage API.
The issue is, it never gets through initialization in Mobile Safari on the first attempt. At around the same point each time, my AJAX calls just stop firing. When I refresh the page, it starts initialization over again, but this time gets through.
If I clear the browser cache and start this process over again, it is always the same. Fail on first attempt, succeed on subsequent refreshes.
I'm aware that there are certain barriers in place in Mobile Safari to prevent large consumption of data unless in direct response to user input (such as the HTML5 audio tag not being able to 'autoplay').
I'm wondering if there is something similar in place for loading web pages for the first time that immediately consume large amounts of data. And by refreshing, Mobile Safari takes that as your explicit permission to do so.
Anyone know?
I suggest you start with a simple, quick-loading base html file, which will give your user something to look at right away -- even if it's just a simple "Loading...".
Then use ajax to get your "loads of data," using window.onload for example. Ideally give your user something to read or interact with so they don't notice the wait, or a progress indicator, to know the site is actually working.
People are impatient, and when faced with a blank screen and the browser loading indicator not making progress, they're going to assume your site is broken within a few seconds.
The certain barriers...to prevent large consumption of data are probably there for exactly this reason, to improve user experience and prevent monstrous web pages.

How to open file dialog in Flash 10 "without" user interaction

I want to open a file dialog via FileReference.browse() but I get #2176 error which means that this action can only be invoked upon some user interaction. I'm aware of security considerations but in my scenario I have a thin flash movie which merely displays an image and the whole UI is in javascript (I heavily use javascript <-> actionscript communication).
So the question is - do you think it would be possible to invoke FileReference.browse() upon the user interaction coming from javascript?
No. If it is anything like accessing the clipboard, then you are stuck out of luck. I have tried all sorts of hacks to get around that, from setIntervals to using apply, I even tried using a ByteArray to manipulate code directly. No soap.
For that matter, you'll have to upload the file to a server using FileReference (unless you're using AIR). This is really annoying if you need to have Flash look at it.
The problem is that when Flash makes this type of decision, they are not making those aspects of the classes accessible by code directly. The code responsible for actually accomplishing these things is locked in the native code which is built into the FlashPlayer. We're black-boxed out.
Back when Adobe first updated their security model, and in turn broke quite a few running flash based upload services, there was a
pretty
big
stink.
I believe that some people were working around the new limitation by essentially creating a transparent flash movie, and overlaying on top of an otherwise normal HTML element, to 'trick' the user into giving the flash app input from which to trigger the interaction (where they think they are clicking on a simple html button labeled 'upload' they are actually clicking on the invisible flash element sitting on top of it.)
I've not tried this method myself, but it may give you a direction in which to search for a solution that might work for you.
Isn't this the purpose of object and embed tags in html? When you say the whole UI is in javascript I am assuming you are using html markup as well, though I guess this may not necessarily be the case.
How to embed a flash file in html
How to start a flash file with javascript
Ok. I've found this link: Flash Player 10 FileReference Changes. Apparently there's no workaround for this limitation. I guess I'll have to display a prompt for the user from within the flash movie, so that he/she can "interact" and allow to open the dialog.

Categories

Resources