Reputation: 744
Is anyone able to do this? My code looks like this:
<video loop autoplay id="bgvid">
<source src="/video/blueParticles.webm" type="video/webm">
</video>
When I browse using Chrome, it works fine. When I use cefclient.exe it works fine. However embedding a ChromiumWebBrowser
control, and pointing it to this webpage does not allow it loop. It only plays once.
Upvotes: 1
Views: 840
Reputation: 31
This question is a bit old, but it still comes up on Google searches, so I figured I'd give it an answer. Please be gentle, I'm not a professional programmer so hopefully my answer will be elaborated on or clarified by someone whose code doesn't read like an XKCD cartoon.
First of all, check out this answer that pointed me in the right direction HTML Video won't loop -- The takeaway is if you're overloading GetResponseHeaders in your CEF app, you're going to have to be really careful to build convincing fake response headers or the video won't loop, and it seems from the linked question and my own tests, that looping video in CEF requires a status response of 206 (partial data) instead of 200 (OK).
In my case, I was redirecting the video links to a local video file packaged with the CEF app using a CefShemeHandler. So, I had to build my own generic response with GetResponseHeaders to respond with a status of 200 OK (it's not clear from the question if that's the exact case for OP, but even if it's not my solution should work). Everything worked fine, except looping. When I realized that I needed to respond with a 206, that also meant I needed to tack on some extra headers.
Far and away, the easiest way to figure out what chromium was expecting in turns of a successful response header was to simply load it up in Chrome (note OP's statement that the page worked fine in chrome as a normal webpage), open the Console, click on 'Network', then click on the name of the video file, then click on 'headers'. Now you can see exactly what Response and Request headers are used when looping is working successfully.
The big thing here is that you'll see that Chrome initiates a Request / Response with full headers on EVERY loop, even though it's pulling from Cache! (you'll see it says 'From Cache' on the Network view for every loop but the first one). This means that, not only will your GetResponseHeaders overload have to give information that makes sense on the first loop, it will have give information that makes sense on EVERY loop.
Maybe someone with a better understanding of http can fill us in on exactly what parts of the header are absolutely vital, but as I wasn't sure, I just spoofed everything I saw under response headers. In my case it looked like this --
Accept-Ranges:bytes
Content-Length:4470009
Content-Range:bytes 0-4470008/4470009
Content-Type: video/webm .webm
Date:Thu, 23 Jun 2016 04:12:41 GMT
Etag:"****************"
Last-Modified:Fri, 06 May 2016 06:04:57 GMT
I think the Etag and Last-Modified date must be the same on all Requests to the same file, but I did not test this extensively. Overall, a few tests led me to believe that the important parts were Content-Range and Content-Length. To get the total number of bytes I simply counted the bytes in my file, and it seemed simple enough to use that for Content-Length and use "bytes 0-(contentLength -1)/(contentLength)" for the range. However, this DID NOT WORK!
Going back to Chrome, I noticed that after the initial request, as I pasted in above, the Responses and Requests started looking a bit different. Under the Request header, the Range said "bytes=0-" the first time, and "bytes=442-" every time (loop) after that. As you'd expect, under the Response header the Content Range also looked different on the loops, it said "bytes 442-4470008/4470009" and the content length was 4469567, which is 442 bytes less than the total.
So I simply parsed the Range string on the Request header to find the starting point, so 0 in the case of the first loop and 442 in the case of the loops in my example, and used that to modify my response headers. The Content-Range became "bytes (startingPoint)-(contentLength -1)/(contentLength)" and the Content-Length became contentLength - startingPoint. After that, it loops fine -- like a charm, from a local file, and no gap!
Upvotes: 3