0
votes

I'm working on an embedded device that is recording video on the fly. I'd like to stream that to an HTML5 video element, using our own custom server. I have this almost working and would like some help.

So far as I can tell, I've got libav / ffmpeg doing their job right. I encoded an mp4 in RAM with the moov atom at the start of the file. I've written this file to disk and it plays everywhere it should.

The problem, I think, lies with how I'm responding to HTTP range requests. When I try to do a live stream, I get an initial range request from the browser / player (currently tried Chrome, Firefox, and VLC) for bytes:0-. I responded with some initial bytes. The browser / player actually plays this fine, but never asks again. So the live stream doesn't work, just the first 3 seconds or whatever.

I've looked at the RFC spec of partial content, and my understanding is I'm doing what I should be... Clearly I'm not though. Here is an example of a request / response with Chrome as the requester:


get /live.mp4 HTTP/1.1 host: localhost:1235 connection: keep-alive accept-encoding: identity;q=1, *;q=0 user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.167 Safari/537.36 accept: */* dnt: 1 accept-language: en-GB,en-US;q=0.9,en;q=0.8 range: bytes=0-

HTTP/1.1 206 Partial Content Accept-Ranges: bytes Content-Type: video/mp4 Content-Length: 182400 Content-Range: bytes 0-182399/*


Again, with that request / response pair, Chrome plays the first 182400 bytes but never makes a second request. I thought having the '*' in Content-Range would make this happen...

3
To be clear, I get exactly the same behavior in Firefox and VLC.user2333829

3 Answers

0
votes

Progressive download doesn’t work that way. It browser assumes the file will never change. To play a live stream you need to use fragmented MP4 and media source extensions.

0
votes

This was the problem. I needed media extensions, it wasn't clear to me that progressive streaming wasn't for live feeds of unknown length. Media extensions and a websocket solved the issue. Also needed to use -dash for libav to make it work in Chrome.

0
votes

I came across a similar issue where it was working perfectly on Firebox but only plays the first fragment of the video in Chrome and does not request any other. My case was solved simply by making the very first response return nothing with a 200 status code and Accept-Ranges: bytes header.

Looks like it is common, check the update part for the following question: Content-Range working in Safari but not in Chrome