# webrtcsink All-batteries included GStreamer WebRTC producer, that tries its best to do The Right Thing™. ## Use case The [webrtcbin] element in GStreamer is extremely flexible and powerful, but using it can be a difficult exercise. When all you want to do is serve a fixed set of streams to any number of consumers, `webrtcsink` (which wraps `webrtcbin` internally) can be a useful alternative. [webrtcbin]: https://gstreamer.freedesktop.org/documentation/webrtc/index.html ## Features `webrtcsink` implements the following features: * Built-in signaller: when using the default signalling server (provided as a python script [here](signalling/simple-server.py)), this element will perform signalling without requiring application interaction. This makes it usable directly from `gst-launch`. * Application-provided signalling: `webrtcsink` can be instantiated by an application with a custom signaller. That signaller must be a GObject, and must implement the `Signallable` interface as defined [here](plugins/src/webrtcsink/mod.rs). The [default signaller](plugins/src/signaller/mod.rs) can be used as an example. * Sandboxed consumers: when a consumer is added, its encoder / payloader / webrtcbin elements run in a separately managed pipeline. This provides a certain level of sandboxing, as opposed to having those elements running inside the element itself. It is important to note that at this moment, encoding is not shared between consumers. While this is not on the roadmap at the moment, nothing in the design prevents implementing this optimization. * Congestion control: the element levarages transport-wide congestion control feedback messages in order to adapt the bitrate of individual consumers' video encoders to the available bandwidth. * Configuration: the level of user control over the element is at the moment quite narrow, as the only interface exposed is control over proposed codecs, as well as their order of priority, and disabling congestion control. Consult `gst-inspect=1.0` for more information. More features are on the roadmap, focusing on mechanisms for mitigating packet loss. It is important to note that full control over the individual elements used by `webrtcsink` is *not* on the roadmap, as it will act as a black box in that respect, for example `webrtcsink` wants to reserve control over the bitrate for congestion control. If more granular control is required, applications should use `webrtcbin` directly, `webrtcsink` will focus on trying to just do the right thing, although it might expose interfaces to guide and tune the heuristics it employs. ## Building ### Prerequisites The element has only been tested for now against GStreamer master. For testing, it is recommended to simply build GStreamer locally and run in the uninstalled devenv. > Make sure to install the development packages for some codec libraries > beforehand, such as libx264, libvpx and libopusenc, exact names depend > on your distribution. ``` git clone https://gitlab.freedesktop.org/meh/gstreamer/-/tree/webrtcsink meson build ninja -C build ninja -C build devenv ``` ### Compiling ``` shell cargo build ``` ## Usage Open three terminals. In the first, run: ``` shell cd signalling python3 simple-server.py --addr=127.0.0.1 --disable-ssl ``` In the second, run: ``` shell cd www python3 -m http.server ``` In the third, run: ``` shell export GST_PLUGIN_PATH=$PWD/target/debug:$GST_PLUGIN_PATH gst-launch-1.0 webrtcsink name=ws videotestsrc ! ws. audiotestsrc ! ws. ``` When the pipeline above is running succesfully, open a browser and point it to the python server: ``` shell xdg-open http://127.0.0.1:8000 ``` You should see an identifier listed in the left-hand panel, click on it. You should see a test video stream, and hear a test tone. ## Configuration The element itself can be configured through its properties, see `gst-inspect-1.0 webrtcsink` for more information about that, in addition the default signaller also exposes properties for configuring it, in particular setting the signalling server address, those properties can be accessed through the `gst::ChildProxy` interface, for example with gst-launch: ``` shell gst-launch-1.0 webrtcsink signaller::address="ws://127.0.0.1:8443" .. ``` The signaller object can not be inspected, refer to [the source code] for the list of properties. [the source code]: plugins/src/signaller/imp.rs ## Testing congestion control For the purpose of testing congestion in a reproducible manner, a [simple tool] has been used, I only used it on Linux but it is documented as usable on MacOS too. I had to run the client browser on a separate machine on my local network for congestion to actually be applied, I didn't look into why that was necessary. My testing procedure was: * identify the server machine network interface (eg with `ifconfig` on Linux) * identify the client machine IP address (eg with `ifconfig` on Linux) * start the various services as explained in the Usage section (use `GST_DEBUG=webrtcsink:7` to get detailed logs about congestion control) * start playback in the client browser * Run a `comcast` command on the server machine, for instance: ``` shell /home/meh/go/bin/comcast --device=$SERVER_INTERFACE --target-bw 3000 --target-addr=$CLIENT_IP --target-port=1:65535 --target-proto=udp ``` * Observe the bitrate sharply decreasing, playback should slow down briefly then catch back up * Remove the bandwidth limitation, and observe the bitrate eventually increasing back to a maximum: ``` shell /home/meh/go/bin/comcast --device=$SERVER_INTERFACE --stop ``` For comparison, the congestion control property can be set to disabled on webrtcsink, then the above procedure applied again, the expected result is for playback to simply crawl down to a halt until the bandwidth limitation is lifted: ``` shell gst-launch-1.0 webrtcsink congestion-control=disabled ``` [simple tool]: https://github.com/tylertreat/comcast ## License All code in this repository is licensed under the [MIT license]. [MIT license]: https://opensource.org/licenses/MIT