I'm working on my own DRM solution for video content. I'm verifying each access to the actual video file. So video.mp4 is actually video.php which then streams orig_vid.mp4 into a <video> element.
It works fine and all – except on mobile! Mobile seems to access the video file two times, making the second request unverifiable.
Before the video is played (autoplay not possible on mobile) it accesses the file once, probably to get headers, etc. Then another request is coming throug, once we hit the play button (as expected), but after that, there's another request, and I can't figure out why or how to validate this request.
If at least I know the pattern behind the requests, I could build my script so it accommodates those. But to me right now the 2 requests seem random...
Any idea or explanation why that is or what's going on?
Are there Cache-Control, Date and Expires headers properly set?
Related
I have a video element with a mp4 source
<video src="https://dh2jw0564x0cd.cloudfront.net/projects/6a30cb01-4414-4c50-ac7e-c2d9ac30358d/assets/videos/1646314487232_Big_Buck_Bunny_1080_10s_1MB.mp4" controls preload="auto"></video>
looking at the network tab I see inconsistent behavior
sometime I dont see the request for the video at all
when I press play I see a new request with 206 response (range)
sometimes the content length of the first request is the size of the whole video, but I do see following requests (with 206 responses) even though the whole video was already downloaded (wtf)
pause and play creates more http requests for the video
I tried to find info online but if someone can shed some light on this it will be very helpful...
All an all it seems very inconsistent and I'm trying to find out if data is being downloaded again even though it is already downloaded...
network tab
I'm streaming a dynamically-generated MP4 into a webpage over a WebSocket. I assemble a MediaSource (https://developer.mozilla.org/en-US/docs/Web/API/MediaSource) as the fragments come in, use that for the HTML5 video element, and my video plays fine in all major browsers.
What I'd like to do is add the ability for a user to download this video. My first attempt was to see if I could get access to it through the video.src property, which I set with window.URL.createObjectURL(my_media_source). This URL is a blob URL of the form "blob:null/abb348e0-3459-8344-bf1e-063dd001f09a". I don't know why there is a null in that url, but it is consistently there. An XMLHttpRequest to get this blob fails.
So, what is the right way to take my streaming video that plays fine and download it as a single file? The MediaSource seems to contain the entire video stream -- can I get access to that as an arraybuffer or a blob or whatever?
I think I answered this on my own. To my understanding, here is the present situation:
First off, it appears that getting the binary data back from a MediaSource is actually not currently possible. There is even an issue about this on the W3C standard: https://github.com/w3c/media-source/issues/209
What is possible is using the relatively new MediaRecorder (https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) API, which is not yet supported by all browsers. The downside of this is that the browser re-encodes the video and you have less control over the output format -- I couldn't get Chrome to produce an mp4, only a webm. Also, if there was a previous request for binary data, every time you request the binary data, it will only give you the data starting from that previous request.
Of course, one could also manually keep a second copy of the video in memory, but I didn't want to follow that approach as it seemed very wasteful and annoying.
I am attempting to write a web service (using C# and WebAPI, thought the actual server technology likely isn't important) that hosts dynamic video files for consumption by a basic HTML5 video element.
Here is my situation and my requirements:
The video is being transcoded on the fly and so the final file size is not known. I cannot provide a Content-Length. However, the time duration of the video is known in advance.
The video must be immediately playable when the page loads, even if it's not done transcoding.
The user must be able, via the HTML5 video controls, to seek backwards and forwards in the video. If they attempt to seek forward to a point that is not transcoded, the request will block until the transcoding catches up.
I tried to use a 206: Partial Content response with the Content-Range header but since I am unable to provide a content-length, the player in Chrome seems unable to seek beyond the first chunk of video it gets and the player in Firefox doesn't even attempt to download more than the first chunk. It is also invalid to respond with a range outside what is asked for by the client but the video player always asks for bytes 0+.
Without a content-length, I considered using Transfer-Encoding: chunked and chunking the output. However, Chrome does not let you seek through a video if the server does not support ranged requests.
I have also considered specifying a fake content length of 1TB or something ridiculous just so I can do the ranged response option but I do not know if that will affect the progress bar or seek capabilities. Does the HTML5 video player determine the progress bar's dimensions based on file size or duration?
So what are my options? I am sure this is a problem that's been solved before. Can ranged responses be used in conjunction with chunked encoding?
It looks like Chrome downloads from the beginning of a file when scrubbing past the buffered/loaded duration, even though the 'seekable' amount claims to be 100%.
I put up a demo page hardcoded to a 59 min audio file stored on s3, but otherwise identical to the jPlayer demo:
http://beta.prx.org/jplayer_demos/demo-01-supplied-mp3-bm.htm
I'm testing on a Mac (10.6.8):
On Safari (5.1.4), if you scrub past the loaded/buffered duration, it initiates another request using the range header, and gets the audio from that point almost instantly.
On Chrome (17.0.963.79), when you scrub beyond the buffered/loaded duration, it sits and spins until it can load the audio from the beginning to the duration scrubbed.
Any idea how to make Chrome behave itself and use the range header when you scrub past the loaded part of the audio file?
I was driving nuts with this. I'm implementing a web player with jPlayer too and they talk on the dev guide about the "Accepts-range" HTTP header and how it mess with Chrome, but thanks to you I realised it's a HTML5 audio tag problem... so much time wasted.
FIX: add the parameter "solution: 'flash, html'" on the jPlayer constructor to change to flash by default.
Using the same video twice in the same page seems to force an unnecessary media reload.
Compare loading a video to loading an image:
<img src="image.png"/>
<img src="image.png"/>
<video src="video.webm"></video>
<video src="video.webm"></video>
According to the Firefox 5 web console, this loads the image once, but the video twice.
I understand from http://www.w3.org/TR/html5/video.html#dom-media-mediagroup that the spec's authors expected a single reload in both cases ("Multiple media elements referencing the same media resource will share a single network request"), but that is not happening to me.
I have tried to play around with server cache parameters (I'm using vanilla web.py), to no avail, and I suspect that's barking at the wrong tree. Is there anything specific I should be looking at? HTML meta elements?
Note that this is the opposite of common issues with having multiple sources for the same video. Here I am concerned with having multiple video elements with the same source playing side by side (e.g. at different points in time).
I think people are misreading the spec here.
If you look at the example in the spec, they specifically talk about a single resource (file) that contains multiple tracks. The two video elements contain a reference to the same file, but different tracks within that file. The two tracks are then played back in sync by means of a media group.
If you have two video tags that reference the same file with the same track, I would not expect them to play in sync by default. I could imagine that by specifying them in the same media group this might achieve that, and therefore allow both elements to use a single connection with a single stream of requests.
If the two videos are not going to be playing in sync, it is unreasonable to expect the browser to load the two videos across a single request set. Note that this is a request set, a video may generate many requests to a server as a video or media session (think stop, pause and restart) may be significantly longer than a server or client is willing to hold open a single connection.
Imagine if the two elements had different controls. You pause the first video and leave the second video playing. 30 minutes go by, and you restart the first video. The browser is simply not going to have cached what might amount to over a hundred megabytes of content from the server to allow it to play the first video without making a new request to the server.
If you expect two discrete pieces of streaming content to be sent over a single connection using HTTP, then I don't believe that is possible (well, currently implemented). That would be multiplexing, and last I checked, HTTP servers don't have any support for multiplexing. Note that this is different from a keep alive connection where multiple pieces of content are served serially, what multiplexing is describing is multiple pieces of content being served in parallel. The usual way to achieve this is simply to have two sockets open, which is a lot simpler for both client and server to deal with than trying to demux a single stream.
If you check the size of the downloaded video, are they both downloading the full video?
In my tests, most browsers download a small chunk (enough to display the thumb) and then the full video when needed - so I'm wondering if you are counting that as two full downloads, when it is actually only one full download and one partial.
I did some tests in June with the help of Bruce Lawson and we discovered that some browsers perform even more loads than the two I've described above.
HTML 5 Video In Real Life (Tests)
If you are using Html 5, then better you can go with Canvas. It will Load the video once.
This work:
<video id="video" class="videohtml5" width="720" height="500" controls="controls" preload="auto" poster="">
<source src="path(1)" />
<source src="path(2)" />
<source src="path(3)" />
</video>
You could of course put the videos in thumbnails and have them load when someone clicks on them, it might help if you can't find something else.
Sounds like this is a bug in the browser you're using, since it's apparently not adhering to the W3C HTML 5 specification. I would recommend you file a bug report for that browser's devs and test to see how this behavior compares with other browsers.
I think it's because you not enabled webm or mp4 resource caching in your server, can check your request header to see if the cache-control exist.