Search code examples
ffmpegvideo-streaminghtml5-videohttp-live-streaminglibav

HTML5 Progressive Streaming -- no follow-up range requests


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


Solution

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