I'm trying to ensure (to the extent possible) that an HTML5 video begins playing only only when it is able to play through completely without buffering. For context, the MediaStream of the video is then used to mix with another audio source and sent over peer WebRTC connections. The videos are typically 5-10MB and a few minutes long (i.e. a decent broadband connection should have no trouble loading the entire video well before it's done playing).
To achieve this, my code currently waits for the canplaythrough event on the video element to begin and calls play() when it fires.
This "works" in the sense that the video begins playing and, in most cases, buffering is sufficient for the video to play through uninterrupted. But, in a few cases (specifically for two people so far that happen to both have been running Chrome on MacBook Airs and with apparently not incredible but decent broadband Internet connections) the video plays staggered and choppy---which I believe to mean the video has not sufficiently buffered.
Are there better techniques for either ensuring that video is sufficiently buffered on most browsers?
Would using fetch() to buffer the entire video in memory probably do the trick? Or is a resulting blob() also actually lazily buffered behind the scenes?
Are there good practices for testing and debugging these sorts of issues given that I can't really replicate this locally?
I have built a tool called Stream or Not that might help on the network side. It will tell you how long the video takes to start, how many stalls, etc. You can use your browser's devTools to throttle the network (and in Chrome, you can emulate the CPU).
Honestly - to see if the network is the issue, as long as the bitrate (use FFprobe https://www.streamclarity.com/probe?url=) is lower than the network speed, you are not network constrained.
There is another possibility. What are the dimensions of your video? How what are the dimensions of the viewport on the browser? If you are asking the device to chop down a lot of pixels - the playback limit might move away from bandwidth to CPU processing speed. I have seen this happen on mobile devices and on older Macs trying to play 4k videos - there just isn't enough CPU to process that many pixels.
I'd test the network speeds, just to be sure.
Make sure you are not sending more pixels than you need. Underpowered devices will have issues.
Related
Is there any way possible to make HTML Video run off of internet, and buffer when the internet connection is weak, or low, for example, the YouTube Player, The basic idea is to chop video, and buffer it before the client clicks play, can this be based on internet connection and wifi? I will do anyway possible to implement this feature!
Thank you.
IMHO, the video element does most of the buffering in the background (depending on the internet connection), and is usually quite good at it. From experience, it is more time-efficient as a developer to try to optimize the size/quality of the streaming video (using tools like Handbrake) rather than try to alter buffering depending on network variables.
That being said, if you are mainly targeting mobile devices, you could could use the experimental Network Information API to get info in Javascript what kind of mobile connection the device is using, and then direct them to a different (low quality) version of the video if they are using 3g or slower.
Alternatively, if you just want the video to start preloading (not playing) as soon as the page loads, have a look at the preload feature on the html video element.
I'd like to know how YouTube plays long-form videos so quickly, with seeking, on mobile.
This is an example video: https://www.youtube.com/watch?v=eyU3bRy2x44
I can load it just fine on mobile within 5-15 seconds and I can even seek through it.
Are they using HLS? Or are they using any other streaming technology? Are they using MP4 with highly optimized MOOV Atoms placed at the front of the files?
I'd like to know because I want to serve up long-form videos on one of my websites, and they take forever to load even if served from a CDN.
Thank you in advance!
Your videos should not really take a long time to load even with 'normal' HTTP streaming if the CDN is doing its job properly.
One possible problem might be the quality/bit rate of your videos - if they are only available in high quality or high bit rate then this will definitely cause a delay in initial playback.
Many (most?) YouTube videos now will support multiple bit rates, which allows the client device select the bit rate that is most appropriate for the current network conditions. This technique is called adaptive bit rate streaming, as you likely are aware given the reference to HLS above.
MPEG DASH, as Aquary mentions, is an adaptive bit rate streaming format. It is designed to be an open standard - Apple's HLS, Microsofts's Smooth streaming and Adobe Dynamic Streaming are the other main adaptive bit rate formats.
For videos that support adaptive bit rate streaming the client will usually start up at a low or medium bit rate to ensure quick start up and then 'step up' to the highest bit rate the network will support once the video is playing. This helps fast startup. When you jump to the middle of a video the same approach is used to 'start' again from the point you have selected.
You can quite often see this if you look closely at a video when it starts up - the playback quality will improve after a short while as the video steps up through the bit rates to higher quality streams.
YouTube uses MPEG-DASH in HTML5 on the devices that are capable of that. This allows seeking through the media and start from the moment which you select.
Traditional progressive download (AKA pseudo-streaming) is not a good option in case of long videos because by default, media players try to download entire video even though you may stop the playback. Seeking is also supported in PD but your video should be prepared for that and your media server needs to be able to process seek requests properly.
I've got an HTML5 <video> element whose source is a .m3u8 (HLS stream)
I have an M3U8 with three different renditions: 640x360, 960x540, and 1280x720
On Desktops I have a Flash Player for playing the video, so the HTML5 fallback is only intended for mobile (iOS and Android) - I am doing all of my testing on an iPad and, once it's working, I will try it out on Android and hope everything works the same.
My goal is to, at any point in time, figure out what rendition the video element is playing. The rendition is subject to change as the user's bandwidth changes.
I tried using the .videoHeight property, but it always returns 480 regardless of the rendition being downloaded - which is particularly odd because 480 isn't even an option.
Does anyone know how I can figure out the rendition being downloaded?
Cleaning up some old questions that never received answers:
Unfortunately this one is just not possible. The HTMl5 video spec and HTML5 video implementations in most browsers are intended to abstract away all of the underlying magic involved in playing videos. You give it a source, it plays. Everything else is completely hidden and you have no access. No access to metadata channels, no access to audio channels, no access to bitrate and resolution information,...
At best I developed a solution to guess which resolution was playing. Every 10 seconds a 1 MB file was loaded over AJAX. I measured the speed at which this downloaded to guess at their current bandwidth. I know that QuickTime will only play a rendition if you have double the required bandwidth. So if the 960x540 rendition requires 1400 kbit/s then it won't play unless you have 2800 kbit/s bandwidth.
It's not very good (and wastes 6 MB of bandwidth per minute) but it's better than nothing.
I need to display several items on a page that represent videos. Embedding video players (even just a couple) causes a ton of load on the user's CPU (you can hear your computer's fan spin up immediately to the maximum speed). My thought to mitigate this is to generate animated GIFs to represent clips of the videos. This seems to cause a load on the CPU but not nearly so great. It seems that once the GIFs have finished loading, the CPU load is less of an issue.
I'm only testing this by putting about 15 GIFs on a page, loading it up in Chrome on my MacBook Air and watching Activity Monitor.
http://yawmp.com/temp/anigif_test.php
Is my logic sound that Animated GIFs require much less CPU resources than embedded videos? Are there memory issues I should be concerned about? Are there any downsides to going this route in terms of system resource pain for my users?
If there are a few frames in the animated gif, the browser is just cycling through those frames - that isn't a particularly big deal. The memory issue would become a problem if you put enough of them on a page.
However, that is a lot of stuff moving, flickering and otherwise demanding attention. Maybe you could switch from a static preview image to the animated gif on mouse over so there is a bit less going on at once. Then if it interests them they can click through and load the video.
I'm building a large flash site (AS3) that uses huge FLVs as transition videos from section to section. The FLVs are 1280x800 and are being scaled to 1680x1050 (much of which is not displayed to users with smaller screens), and are around 5-8 seconds apiece. I'm encoding the videos using On2's hi-def codec, VP6-S, and playback is pretty good with native FLV players, Perian-equipped Quicktime, and simple proof-of-concept FLV playback apps built in AS3.
The problem I'm having is that in the context of the actual site, playback isn't as smooth; the framerate isn't quite as good as it should be, and more problematically, there's occasional jerkiness and dropped frames (sometimes pausing the video for as long as a quarter of a second or so). My guess is that this is being caused by garbage collection in the Flash player, which happens nondeterministically and is therefore hard to test and control for.
I'm using a single instance of FLVPlayback to play the videos; I originally was using NetStream objects and so forth directly but switched to FLVPlayback for this reason. Has anyone experienced this sort of jerkiness with FLVPlayback (or more generally, with hi-def Flash video)? Am I right about GC being the culprit here, and if so, is there any way to prevent it during playback of these system-intensive transitions?
Jerkiness in FLV/F4V playback is hardly the result of garbage collection - the video is actually kept in memory until it is fully unloaded, so there's no garbage collection taking place at all (unless you've done something unorthodox like placing the video on a container with cacheAsBitmap set to true).
Switching to F4Vs if you don't need specific FLV features (like the link posted by daidai suggests - disclaimer, it's my blog) would help, but overall, you also have to be aware of anything that's impacting compositing of the video on screen. Because a big size video forces everything that's overlapping it to be re-rendered, any small object can have a big impact on performance.
Do you have things on top of the video? Try getting rid of them, if possible, or setting cacheAsBitmap to true (if they're not animated). This is specially good for complex vector drawings or text (bitmaps/images are much faster to draw). If they have different blending modes, you're sort of screwed - can you use the normal blending mode instead?
Do you have anything below the video? If so, get rid of them while the video is playing (just set visibility to false).
To check on unnecessary renderings, somehow pause the video, right-click, turn on 'show redrawn regions' (debug player). Do you see the red square drawing continuously? Then there's something happening there on the background, better to get rid of it.
Do you have anything happening on the background via onEnterFrame or timers/intervals? Try pausing it.
Is your video 30fps, and a CG rendering (eg, can use motion blur)? If yes, try rendering at 24fps instead, or something between - still good quality, but much less data to decode and draw.
Can you use smaller videos? Even if you're still rendering them at the same bigger size, less pixel data to decode and render helps immensely, and the impact in quality can be pretty small.
That pretty much sums it all. Getting rid of everything else on screen is usually your #1 priority though.
Have you tried encoding the videos in H.264 instead? Flash player supports them for some time now, it may end up working better. That's what most people doing HD video in Flash use (eg Youtube, Vimeo, etc).
Just as a test, try plaing a 1080p HD video on youtube and see if that pauses at all for you.
Check out http://zehfernando.com/2010/benchmarking-video-playback-performance-in-flash/