davedoesdev / streamana

Stream from your Web browser to YouTube Live. No plugins or native apps required!
http://rawgit.davedoesdev.com/davedoesdev/streamana/publish/site/streamana.html
MIT License
54 stars 10 forks source link

= Streamana

== Description

Streamana is a Web page which streams your camera and microphone to YouTube Live (or any other HLS or DASH receiver). It uses https://github.com/davedoesdev/webm-muxer.js[webm-muxer.js] and https://github.com/davedoesdev/ffmpeg.js[ffmpeg.js].

== Demo

You can see it in action http://rawgit.davedoesdev.com/davedoesdev/streamana/publish/site/streamana.html[here]. Use Chrome 95 or later.

. Get your ingestion URL from https://studio.youtube.com[YouTube Studio]. .. Click CREATE and then select Go Live from the drop-down menu. .. Under Select stream key, select Create new stream key. .. Give your key a name. .. You must select HLS as the streaming protocol. Note: YouTube DASH ingestion is only available by using the Youtube API. See https://developers.google.com/youtube/v3/live/guides/encoding-with-dash#url-structure[here] for more details. .. Click CREATE. .. Make sure the key you created is selected. .. Click COPY next to Stream URL. . Paste the URL into the Ingestion URL box in Streamana. . Click Live. ** If you want to see what's happening under the hood, open developer tools (F12). . To end the stream, click Live again.

You can also change various options:

== Customisation

You can change the look and feel of Streamana by editing link:site/streamana.html[] and link:site/streamana.css[].

The camera video is passed through a WebGL fragment shader in link:site/shader.js[] so you can change this to add video effects or overlays. The shader already handles resizing and rotating the video in main(). The optional greyscale conversion is in the tpix() function.

The page's functionality is defined in link:site/streamana.js[] and link:site/streamer.js[].

link:site/streamer.js[] exports a function, get_default_config_from_url, and a class, Streamer, which does the heavy lifting.

You should first call get_default_config_from_url. It takes a single argument, the URL of ffmpeg-worker-hls.js or ffmpeg-worker-dash.js in https://github.com/davedoesdev/ffmpeg.js[ffmpeg.js]. This allows your application (or the end user if required) to supply its own version, in accordance with LGPL. It can be a relative path (i.e. just ffmpeg-worker-hls.js or ffmpeg-worker-dash.js).

get_default_config_from_url determines the streaming protocol (hls or dash) and returns the default configuration for the protocol:

{
    ffmpeg_lib_url, // the URL you passed to `get_default_config_from_url`
    protocol, // `hls` or `dash`
    video: { // properies of the video you will be supplying
        bitrate: 2500 * 1000,
        framerate: 30
    },
    audio: { // properties of the audio you will be supplying
        bitrate: 128 * 1000
    },
    media_recorder: { // default options for MediaRecorder if it ends up being used
        video: {
            codec: protocol === 'dash' ? 'vp9' : 'H264', // video codec
        },
        audio: {
            codec: 'opus' // audio codec
        },
        webm: true, // container format
        mp4: false // if true, requires ffmpeg-worker-hls.js or ffmpeg-worker-dash.js
                   // to be configured with MP4 support (which is not the default)
    },
    webcodecs: { // default options for WebCodecs if it ends up being used
        video: {
            // video codec and options
            ...(protocol === 'dash' ? {
                codec: 'vp09.00.10.08.01'
            } : {
                codec: 'avc1.42E01E' /*'avc1.42001E'*/,
                avc: { format: 'annexb' }
            })
        },
        audio: {
            codec: 'opus' /*'pcm'*/, // audio codec
        },
        webm_muxer: { // options for webm-muxer.js
            video: {
                codec: protocol === 'dash' ? 'V_VP9' : 'V_MPEG4/ISO/AVC'
            },
            audio: {
                codec: 'A_OPUS',
                bit_depth: 0 // 32 for pcm */
            }
        }
    },
    ffmpeg: { // desired ffmpeg output codecs
        // Note: If the encoded stream already uses the desired codec then
        // it will pass `copy` instead. For example, if your browser encodes
        // your video to H.264 already then `copy` will be used instead of
        // `libx264`. This means you can use `ffmpeg-worker-hls.js` or
        // `ffmpeg-worker-dash.js` that doesn't contain a H.264 encoder.
        video: {
            codec: protocol === 'dash' ? 'libvpx-vp9' : 'libx264'
        },
        audio: {
            codec: protocol === 'dash' ? 'libopus' : 'aac'
        }
    }
};

You application can modify the returned configuration before creating a Streamer object.

Use the Streamer class as follows:

Streamer extends from https://developer.mozilla.org/en-US/docs/Web/API/EventTarget[`EventTarget`] and dispatches the following events:

== Licence

Streamana is licensed under the terms of the link:LICENCE[MIT licence].

Note that https://github.com/davedoesdev/ffmpeg.js[ffmpeg.js] is licensed under LGPL. Streamana runs it inside a Web Worker and communicates with it via message passing. The end user can replace the version used by changing the URL in the user interface.

Note also that the https://github.com/davedoesdev/ffmpeg.js[ffmpeg.js] HLS and DASH distributions contain no H.264 or MP4 code. All encoding is done by the browser using https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder[`MediaRecorder`] or https://www.w3.org/TR/webcodecs/[WebCodecs].