Giter Site home page Giter Site logo

webmcast's Introduction

webmcast

An experimental video streaming service.

The Idea

A generic WebM file looks like this:

EBML.

By setting the Segment's length to one of 7 reserved values (all of which mean "indeterminate"), it's possible to produce an infinite stream.

There is only one reserved word for Element Size encoding, which is an Element Size encoded to all 1's. Such a coding indicates that the size of the Element is unknown, which is a special case that we believe will be useful for live streaming purposes.

Infinite EBML.

Let's say a client connects at some point.

Barely in time for the best part.

Naturally, we have to send the EBML header and track descriptions first. We can't just start forwarding frames yet, though. Each WebM frame may depend on three previously-seen frames: the last keyframe, the previous frame, and an Alternate Reference frame, none of which the client has yet, causing a decoding error if one is needed. The solution is to only start from the next keyframe, which, by definition, references nothing; sending it is always OK. Further frames cannot reference any frame that came before the keyframe, so we can proceed as normal.

Oops, sorry, it was dropped.

Additionally, a WebM file (even an infinite one) can contain multiple segments. These segments will be played one after another if they contain the same tracks, so we can spawn a copy of the original stream with a different bitrate, then switch the client over by starting a new segment if a slow connection is detected. Kind of like adaptive streaming, see?

It's not the size of a cluster, it's the contents.

Sounds simple, huh? So simple, in fact, someone probably already thought to do that. That's right! We're live-streaming Matroska!

The Implementation

This code!

go build -i
./webmcast

How To Broadcast Stuff

PUT/POST a WebM to /stream/<name>. (Note that you have to register first, to obtain said name and a token.)

server=http://localhost:8000
name=test

ffmpeg $source \
    -c:v vp8 -b:v 2000k -keyint_min 60 -g 60 -deadline realtime -speed 6 \
    -c:a opus -b:a 64k \
    -f webm $server/stream/$name?$token

Or with gstreamer:

gst-launch webmmux name=mux streamable=true ! souphttpclientsink location=$server/stream/$name?$token \
           $video_source ! videoconvert ! vp8enc keyframe-max-dist=60 deadline=1 ! queue ! mux.video_0 \
           $audio_source ! vorbisenc ! queue ! mux.audio_0

Tips:

  • -g (or keyframe-max-dist) controls the spacing between keyframes. Keep it low (~2 seconds) to allow the stream to start faster for new viewers. ffmpeg tip: use -force_key_frames 00:02 instead if you don't know the framerate.

  • The stream may be split arbitrarily into many requests. For example, gstreamer sends each frame as a separate PUT by default.

  • The stream is kept alive for some time after a payload-carrying request ends. Thus, should the connection fail, it is possible to reconnect and continue streaming as if nothing happened. (Duplicate WebM headers are ignored.)

  • Multiple WebM streams can be concatenated (or sent as multiple requests to the same stream), as long as they contain the same tracks and use the same codecs. For example, you can switch bitrate mid-stream by restarting ffmpeg.

  • Sending frames faster than they are played back is OK. However, frames may or may not get dropped if buffers overflow, and clients that do not connect at the same time are likely to be severely desynchronized (and confused). ffmpeg tip: -re caps output speed at one frame per frame. gstreamer does that by default.

How To View Stuff

Visit /<name> in a web browser. There's a chat and everything. Alternatively, open /stream/<name> in a browser or a video player; a raw WebM will play.

The Reality (alt. name: "Known Issues")

As always, what looks good on paper doesn't always work in practice.

  • There are 7 ways to encode an "indeterminate" length. Naturally, the one that ffmpeg happens to use makes Chrome (48.0.2564.109/CrOS) crash. (The server will automatically recode it as one of the acceptable variants.)

  • When streaming from a webcam (not a random downloaded file for some reason) in VP9, Chrome crashes upon receiving the first frame (even when simply opening a file recorded with ffmpeg), Firefox loses most of the color (and stutters; however, this is likely because encoding & decoding VP9 is too CPU-intensive for my computer to handle), and VLC complains about a missing reference frame. Curiously, curl | ffmpeg accepts the stream just fine. All four use the same library (libvpx) for decoding, so...WTF?

  • VP8 is OK, though.

  • Of course, this thing is incompatible with static CDNs. For redistibution, additional instances must be run on separate servers and connected to form a directed tree.

Looks like all those overcomplicated standards like HLS or DASH exist for a reason, huh?

webmcast's People

Contributors

pyos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.