nginx 404 handling: hls shenanigans part 2

I posted a few weeks ago with an idea for how to make sure that a video stream stays alive even if the source has disconnected. A few folks pointed out that this is unlikely to work very well, but I figured I'd give it a try anyway.

I have an "infinite colorbars video stream" working now, I think. Does it work for you on your various devices? Video stream is embedded above, source. "Works" means "continues playing looping colorbars for longer than two minutes."

Second problem is, how do I get nginx to redirect to this when an index.m3u8 file goes 404? I tried this and it is not working:

location ~ index\.m3u8$ {
  error_page 404 https://videocdn.dnalounge.com/video404/index.m3u8;
}

Under normal circumstances, nginx is filling up /var/run/hls/live/ with several .ts files and a single index.m3u8 file. When the source disconnects, the .ts files expire one by one, and when none are left, the .m3u8 file and the the enclosing directory, /var/run/hls/live/ also disappear. So maybe that's causing problems with the 404 handler?


Update: I got the 404 handling working. The file /live.m3u8 normally contains a list of the two sub-streams, a full and a downcoded version. But when it would have gone 404, it instead contains the contents of /video404/index.m3u8, which is the looping colorbars. But, it doesn't really work. First, the transition from "video" to "colorbars" is not immediate; one has to click play again, which kind of defeats the purpose. And second, the transition back from colorbars never happens! The colorbars just keep playing on a loop forever (until one hits reload), even after /live.m3u8 no longer has colorbars in it.

So, it was a long shot, and everything sucks.

(And yeah, apparently no browsers except Safari support .m3u8 files natively; it only works if the VIDEO element is wrapped in videojs witchcraft as I do on the webcast page. Here it is by itself.)

Previously, previously, previously.

Tags: , , , ,

27 Responses:

  1. Dave Polaschek says:

    The embedded stream seems to work on my iPhone, but I’m figuring that’s the fish in a barrel case.

  2. Colin Rafferty says:

    Works fine in Reeder from RSS feed, both on iPad and iPhone running latest OSes.

  3. Nik says:

    Sorry - the embedded video doesn't last more than a couple of seconds on this Android 11-based oppo phone.

    • jwz says:

      "A couple" or "6"? If it's not 6, it's not even making it to the end of the .ts file, which would be very weird.

  4. Jason says:

    "No video with supported format and MIME type" in the latest Firefox on Win7, which may admittedly be in your "suck it, loser" support tier.

    • jwz says:

      I had the wrong Content-Type on the .ts file so that may have been a problem, but it still doesn't play for me in Firefox, but then, neither does this, which I know is fine. Maybe the VIDEO element in Firefox just doesn't work unless it has videojs wrapped around it?

      • Jon says:

        Years ago, when i set up a small video service for sharing private videos, it helped to provide an additional ogv source which would be picked by Firefox.

      • g says:

        firefox won't implement hls (or dash) for licensing reasons (thanks, mpeg-la!). you'll need to wrap it with https://github.com/video-dev/hls.js/ (slimmer wrapper than video.js; keeps native controls)

  5. Doctor Memory says:

    No dice on Chrome 92 on MacOS Big Sur -- the background image is displayed along with the play/pause/fullscreen controls, but the controls aren't clickable and there's no actual animated video.

  6. Saxmaniac says:

    Looks good in an RSS (feeddler) reader on iPad.

  7. Al Iverson says:

    M1 Macbook Air with Big Sur here. Works fine in Safari, seems to play for as long as I let it, tried it for 2+ minutes. On Google Chrome, the preview shows but nothing seems to be clickable. If I try to "download the video file" I get a stub file that doesn't seem playable in VLC or anywhere else that I can figure out.

    Good luck! This is still pretty cool, feels like a good start.

  8. apm74 says:

    Windows 10 here. On FF Embedded video widget on this page says "No video with supported MIME type found". On Edge, the video player loads up the first frame and looks promising but the play button never enables.

    Trying to open the m3u8 URL directly in FF or Edge tries to hand it off to ITunes which does nothing useful with it.

    Tried Windows Media Player 12.0, opened the m3u8 URL inside there and that plays the video for ~36 seconds (repeats the 0:06 videos six times it seems?) before I'm asked to "Play Again?" or return to my library.

    I don't have VLC on this laptop.

  9. ssl-3 says:

    You always try so hard to get things to work in the One, True Way. And you've certainly earned this desire in the most-honest of ways.

    On behalf of viewers like us, thank you.

    On recent Windows 10 with recent Chrome, I get nothing playable from any of the clickable things in this article. The closest I can get is a .m3u8 file that Chrome does not play, but does offer to download. Once downloaded, Windows opens it in VLC, and then VLC fails to play anything.

    I don't observe an embedded video stream at all.

    Am I holding it right?

  10. dusoft says:

    "No video with supported format and MIME type" in the latest Firefox on Linux as well. When trying to download, VLC offers to open it, but will not play anything.

    • jwz says:

      VLC is garbage, but it plays it fine for me. There are like 12 different ways to open things in VLC, though, so probably you have to tell it "yes this URL is a URL and not a file" because, as I mentioned, it is a garbage program.

  11. McDanno says:

    I don't think you can do a URL-based redirect with a 404 like that in nginx. IIRC you need to change the syntax to one of the following:

    1) Just make it /video404/index.m3u8;

    or
    2) Change the 404 to a 301 via error_page 404 =301 https://...

    I haven't specifically tried using a non-static page for a 404 like that however so I'm curious if it works at all for you.

  12. Carlos says:

    Firefox 91 on Linux here.

    Same "No video with supported format and MIME type" message here. But if I fetch the .m3u I get it with MIME type application/vnd.apple.mpegurl, and then if I download the video file itself I get it with MIME type video/mp2t.

    The resulting file looks like a bog-standard h.264 video in an MPEG transport stream. It plays fine for the full 6 seconds in VLC and in totem.

    Reading around I find statements that Firefox does not natively support MPEG2 transport streams. Apparently https://github.com/videojs/mux.js/ lets you remux the TS stream to an MP4 which it will play, but I don't know if it can be used client-side or not.

    I'm not familiar with HLS - does it require that the files it provides are in TS containers?

    C.

  13. jwz says:

    So everyone's got opinions about m3u8 files, but nobody knows how to do 404 redirects in nginx?

    • Craig MacGregor says:

      That is a really tiny snippet to see anything wrong with, I'm figuring that another stanza's 404 handler is getting in the way.

      I also don't really trust using a full URL in an error_page directive either, but yes, the docs say you can.

      Does nginx treat an "index" file in a special way (or is the included nginx config in whatever Linux distro to blame?) Maybe these are just some ancient flashbacks to Apache.

      Are you testing directly against your origin nginx server instead of Cloudfront? From my POV I'm seeing some pretty seriously long cache ages, and can't bust cache with query params, etc:
      $ curl -si 'https://videocdn.dnalounge.com/blah/index.m3u8' | grep Age:
      Age: 74435

      Feel free to email your nginx config to this stranger to take a closer look... if you think that is a good idea.

    • Troll says:

      I tried this and it is not working

      The config you provided gives zero information on what is actually happening. What does the verbose log say?

      Also, it seems that you have at least change status code to =200, because error_page keeps it 400, so client still thinks that stream is missing. Another thought: what Content-Type does the "404" response have? May be you should change it to something related to m3u instead of text/html.

      Also, try_files might work better than error_page.

      And finally there is nginx-rtmp-backup which runs extra ffmpeg in copy mode, but it seems that it at least works.

  14. Jay Rishel says:

    plays for a few seconds and stops in VLC on Windows. Different lengths on various attempts, +/-1 around 4 seconds. Here is a VLC debug level log file

  15. Matt Lee says:

    Works nicely on Safari and worked nicely on my Apple TV via AirPlay.

  • Previously