Simple WHIP Client (based on GStreamer's webrtcbin)

Overview

Simple WHIP Client

This is an attempt to create a simple prototype of a WHIP client, to be used mostly for testing with my Simple WHIP Server (based on Janus), as well as interoperability testing with other WHIP implementations. As such, it's very early stages, and mostly meant as a playground for interested developers.

Building the WHIP client

The main dependencies of this client are:

Make sure the related development versions of the libraries are installed, before attempting to build the client, as to keep things simple the Makefile is actually very raw and naive: it makes use of pkg-config to detect where the libraries are installed, but if some are not available it will still try to proceed (and will fail with possibly misleading error messages). All of the libraries should be available in most repos (they definitely are on Fedora, which is what I use everyday, and to my knowledge Ubuntu as well).

Notice that, while the Makefile assumes a Linux build, at least in principle it should be possible to build it on other platforms as well, as it makes us of cross-platform dependencies. In case you're willing to submit enhancements to the Makefile to build the client on Windows and/or MacOS as well, it would be more than welcome.

Once the dependencies are installed, all you need to do to build the WHIP client is to type:

make

This will create a whip-client executable. Trying to launch that without arguments should display a help section:

$ ./whip-client
Usage:
  whip-client [OPTION?] -- Simple WHIP client

Help Options:
  -h, --help            Show help options

Application Options:
  -u, --url             Address of the WHIP endpoint (required)
  -t, --token           Authentication Bearer token to use (optional)
  -A, --audio           GStreamer pipeline to use for audio (optional, required if audio-only)
  -V, --video           GStreamer pipeline to use for video (optional, required if video-only)
  -S, --stun-server     STUN server to use, if any (hostname:port)
  -T, --turn-server     TURN server to use, if any (username:password@host:port)
  -l, --log-level       Logging level (0=disable logging, 7=maximum log level; default: 4)

Testing the WHIP client

The WHIP client requires at least two arguments:

  1. the WHIP endpoint to publish to (e.g., an endpoint created in the Simple WHIP Server);
  2. the partial GStreamer pipeline to use for audio, if audio needs to be sent;
  3. the partial GStreamer pipeline to use for video, if video needs to be sent.

Audio and video are both optional, but at least one of the two must be enabled.

A simple audio/video example, that assumes the specified endpoint requires the "verysecret" token via Bearer authorization, is the following:

./whip-client -u http://localhost:7080/whip/endpoint/abc123 \
	-t verysecret \
	-A "audiotestsrc is-live=true wave=red-noise ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay pt=100 ssrc=1 ! queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=100" \
	-V "videotestsrc is-live=true pattern=ball ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay pt=96 ssrc=2 ! queue ! application/x-rtp,media=video,encoding-name=VP8,payload=96"

In case, e.g., STUN is needed too, the above command can be extended like this:

./whip-client -u http://localhost:7080/whip/endpoint/abc123 \
	-t verysecret \
	-A "audiotestsrc is-live=true wave=red-noise ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay pt=100 ssrc=1 ! queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=100" \
	-V "videotestsrc is-live=true pattern=ball ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay pt=96 ssrc=2 ! queue ! application/x-rtp,media=video,encoding-name=VP8,payload=96" \
	-S stun.l.google.com:19302

You can stop the client via CTRL+C, which will automatically send an HTTP DELETE to the WHIP resource to tear down the session.

Comments
  • example of playing a mp4 file in a loop -- need help

    example of playing a mp4 file in a loop -- need help

    I am trying to graduate beyond the ball example but the pipeline seems stuck and does not start. What am I doing wrong?

    ./whip-client -u http://serverexample.com:7080/whip/endpoint/drone -t veryverysecret -V "multifilesrc location=drone.mp4 loop=true ! qtdemux ! h264parse ! rtph264pay ! application/x-rtp,media=video,encoding-name=H264,payload=96" -S stun://stun.l.google.com:19302
    
    --------------------
    Simple WHIP client
    ------------------
    
    WHIP endpoint:  http://serverexample.com:7080/whip/endpoint/drone
    Bearer Token:   veryverysecret
    Trickle ICE:    yes (HTTP PATCH)
    Auto STUN/TURN: no
    STUN server:    stun://stun.l.google.com:19302
    TURN server:    (none)
    Audio pipeline: (none)
    Video pipeline: multifilesrc location=drone.mp4 loop=true ! qtdemux ! h264parse ! rtph264pay ! application/x-rtp,media=video,encoding-name=H264,payload=96
    
    [WHIP] Initializing the GStreamer pipeline:
    webrtcbin name=sendonly bundle-policy=0  stun-server=stun://stun.l.google.com:19302  multifilesrc location=drone.mp4 loop=true ! qtdemux ! h264parse ! rtph264pay ! application/x-rtp,media=video,encoding-name=H264,payload=96 ! sendonly. 
    [WHIP] Starting the GStreamer pipeline
    
    
    opened by saket424 3
  • No smooth video when using simple-whip-client and Millicast

    No smooth video when using simple-whip-client and Millicast

    Hi

    We tried to publish an RTSP stream using the simple-whip-client towards Millicast. It works, at least it publishes video to Millicast, but the playback is not smooth, a lot of framedrops, no smooth image, ... When trying the 'old' method, publishing using RMTP, playback is smooth (given the 3sec delay).

    WHIP command:

    docker run -it --rm -e "U=https://director.millicast.com/api/whip/STREAM" -e "T=TOKEN" -e "V=rtspsrc location=rtsp://192.168.30.3/Streaming/Channels/1 latency=0 name=rtsp ! rtph264depay ! rtph264pay config-interval=-1 ! application/x-rtp,media=video,encoding-name=H264" simple-whip-client
    

    I ran the simple-whip-client on both RPI4 and on a X86 Mac OS, both using docker. The DockerFile entrypoint was changed a bit to be able to pass the TOKEN

    ENV U=http://localhost:3000/whip/foo
    ENV T=
    ENV A="audiotestsrc is-live=true wave=red-noise ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay pt=100 ssrc=1 ! queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=100"
    ENV V="videotestsrc is-live=true pattern=ball ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay pt=96 ssrc=2 ! queue ! application/x-rtp,media=video,encoding-name=VP8,payload=96"
    
    ENTRYPOINT ./whip-client -l 7 -u $U -t $T -V "$V" -A "$A" -S stun://stun.l.google.com:19302
    

    GStreamer command

    gst-launch-1.0 \
    rtspsrc location=rtsp://192.168.30.3/Streaming/Channels/1 latency=0 ! rtph264depay  ! flvmux name=mux ! queue ! rtmpsink location="rtmp://live-rtmp-pub.millicast.com:1935/v2/pub/STREAM?token=TOKEN live=1" 
    
    opened by jdvconsult 2
  • on eos signal from sink between src and webrtcbin, disconnect from whip

    on eos signal from sink between src and webrtcbin, disconnect from whip

    EDIT Removed the error listening hacky code.

    Now you pass in an extra param to give it a name of a sink between the source that may end by itself and webrtcbin Typically you're going to have a demuxer or a parser or a decoder anyway so just add a name to that "sink" and pass that name in as a param under -e

    opened by danjenkins 2
  • Initial integration of new ETags support for PATCH

    Initial integration of new ETags support for PATCH

    This is a small set of changes to add some preliminary support for the proposed ETag usages for PATCH, as documented in this early version of the updated WHIP draft: https://github.com/wish-wg/webrtc-http-ingest-protocol/pull/24/files?short_path=6ca9ae6#diff-6ca9ae63875a605dbaf6d8e45c08b5945951d62135ae0661065b7fe9ebb04d84

    I made the same change in the WHIP server as well.

    Notice that, since the WHIP client doesn't support ICE restarts yet, that part isn't integrated.

    opened by lminiero 2
  • add a dockerfile so its easy to test a whip implementation

    add a dockerfile so its easy to test a whip implementation

    Probably don't need all those dependencies in the dockerfile... was a pretty rough and ready thing to get it to work. I'll come back and tidy it up as well as make other parameters controllable

    opened by danjenkins 2
  • Add an option to disable colors

    Add an option to disable colors

    You can already manually change the code to remove colours but you can't do it from the command line.

    Also, if you turn off colours in the codebase, the [WHIP] prefix still has colors.

    opened by danjenkins 1
  • Added option to disable trickle, and send candidates in the SDP

    Added option to disable trickle, and send candidates in the SDP

    As the subject says, this PR adds a "no-trickle" mode: when enabled, the WHIP client will not trickle candidates via PATCH (default behaviour), but will wait for the gathering to complete to then add all candidates to the SDP offer instead. This shouldn't be needed even for servers that don't support trickle, as prflx candidates should still manage to get things working, but it's good to have the option anyway.

    opened by lminiero 1
  • Add support for WHIP Link headers to autoconfigure STUN/TURN

    Add support for WHIP Link headers to autoconfigure STUN/TURN

    This is an attempt to address what's described in #4. As explained there, with GStreamer we can't add STUN/TURN servers after we've sent our offer, which means this code tries to do the same by using OPTIONS instead.

    This feature is disabled by default: to tell the WHIP client to send the OPTIONS and get a list of STUN/TURN servers automatically, you need to pass the -f argument via command line. Notice that this will make the WHIP client ignore any other server you may have passed manually via -S and -T.

    You can test this using the latest version of my WHIP server, which can be configured to return a list of STUN/TURN servers if you configure it accordingly (either statically in the configuration file, or per endpoint if you add them when creating a new one). I made a few tests and this seems to work as expected: of course more interop tests will need to be performed, as the code that processes the Link headers and turns them to addresses that can be used in GStreamer may be a bit flaky.

    opened by lminiero 1
  • Support multiple TURN servers

    Support multiple TURN servers

    Adds support for multiple TURN servers, by adding multiple instances of the -T command line argument. Published as a pull request, rather than a direct commit, as I couldn't test this yet.

    opened by lminiero 1
  • Increase SDP fragment buffer size

    Increase SDP fragment buffer size

    1024 was not enough on a host with both IPv4 and IPv6 addresses. Increase to 4096. We should probably be sending multiple fragments when we overflow.

    opened by jech 1
  • Support for STUN/TURN autoconfiguration via Link headers

    Support for STUN/TURN autoconfiguration via Link headers

    The new version of the WHIP draft adds support for an automatic configuration of STUN/TURN servers to use in WHIP clients:

    https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html#name-stun-turn-server-configurat

    The way it works is that WHIP servers can return a series of STUN/TURN servers (and credentials, if needed) in Link headers in the 201 in response to the HTTP POST (or optionally in response to the OPTIONS too), e.g.:

    Link: stun:stun.example.net; rel="ice-server";
    Link: turn:turn.example.net?transport=udp; rel="ice-server"; username="user"; credential: "myPassword"; credential-type: "password";
    Link: turn:turn.example.net?transport=tcp; rel="ice-server"; username="user"; credential: "myPassword"; credential-type: "password";
    Link: turns:turn.example.net?transport=tcp; rel="ice-server"; username="user"; credential: "myPassword"; credential-type: "password";
    

    The WHIP client can then parse those Link values and add the STUN/TURN servers to its own stack for gathering.

    Unfortunately, this seems not to work as expected with GStreamer's webrtcbin. While there is, for instance, an add-turn-server signal that can be used to add a TURN server dynamically (which is what we now use for adding TURN servers at startup too, as implemented in #2), that doesn't seem to have any effect after the pipeline has been started. I tried delaying the set-local-description call to after we set the servers, and that didn't help.

    Checking the code:

    • add-turn-server calls gst_webrtc_bin_add_turn_server, which in turn calls gst_webrtc_ice_add_turn_server;
    • gst_webrtc_ice_add_turn_server just adds the new server to a hashtable, ice->turn_servers.

    The internal method that actually adds the TURN server to the libnice stack via nice_agent_set_relay_info, though, is _add_turn_server, which is only called by gst_webrtc_ice_add_stream. Since we add a stream when we first create our pipeline, and so always before we prepare an offer, trying to add a STUN/TURN server after that will not work.

    The WHIP draft does have some text about this:

    There are some webrtc implementations that do not support updating the ICE server configuration after the local offer has been created. In order to support these clients, the WHIP endpoint MAY also include the ICE server configuration on the responses to an authenticated OPTIONS request sent to the WHIP endpoint URL sent before the POST requests.

    As such, I'll try to modify the WHIP server to also return a set of STUN/TURN servers in response to an OPTIONS on the endpoint URL, rather than just to the POST as I do now. This way, I can issue an OPTIONS request from the WHIP client before we create the pipeline, which should give us access to STUN/TURN servers we can actually use.

    opened by lminiero 0
Owner
Lorenzo Miniero
I'm getting older but, unlike whisky, I'm not getting any better.
Lorenzo Miniero
VEngine-Client - vEngine: Official Client Module

━ S Y N O P S I S ━ Maintainer(s): Aviril, Tron vEngine is Next-Gen Sandbox-Engine being crafted in C++. In contrast to UE/Unity/ReverseEngineered-Mod

ᴠ : ꜱᴛᴜᴅɪᴏ 15 Sep 7, 2022
Pyth-client - client API for on-chain pyth programs

pyth-client client API for on-chain pyth programs Build Instructions # depends on openssl apt install libssl-dev # depends on libz apt install zlib1g

Pyth Network 115 Dec 16, 2022
Webdav-client-cpp - C++ WebDAV Client provides easy and convenient to work with WebDAV-servers.

WebDAV Client Package WebDAV Client provides easy and convenient to work with WebDAV-servers: Yandex.Disk Dropbox Google Drive Box 4shared ownCloud ..

Cloud Polis 103 Jan 1, 2023
This repository provides a C++ client SDK for Unleash that meets the Unleash Client Specifications.

Unleash Client SDK for C++ This repository provides a C++ client SDK for Unleash that meets the Unleash Client Specifications. Features The below tabl

Antonio Ruiz 4 Jan 30, 2022
Simple server and client using python socket and declarative programming

Socket-programming Simple server and client using python socket and declarative programming How to use? open cmd and navigate to the location of the s

MAINAK CHAUDHURI 24 Dec 17, 2022
Ole Christian Eidheim 741 Dec 27, 2022
wl-mirror - a simple Wayland output mirror client

wl-mirror - a simple Wayland output mirror client wl-mirror attempts to provide a solution to sway's lack of output mirroring by mirroring an output o

Ferdinand Bachmann 118 Dec 29, 2022
Simple Tcp Chat Client / Server written in C++

What this TcpXat TcpXat Is A Simple Tcp Chat Setup TcpXat sudo apt install make;make client;make serv;echo "done by FuryM3m0ry"; How To Run TcpXat Ter

sami 1 Dec 28, 2021
A very simple, fast, multithreaded, platform independent HTTP and HTTPS server and client library implemented using C++11 and Boost.Asio.

A very simple, fast, multithreaded, platform independent HTTP and HTTPS server and client library implemented using C++11 and Boost.Asio. Created to be an easy way to make REST resources available from C++ applications.

Ole Christian Eidheim 2.4k Dec 23, 2022
The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design. This project aims to help C++ developers connect to and interact with services.

Welcome! The C++ REST SDK is a Microsoft project for cloud-based client-server communication in native code using a modern asynchronous C++ API design

Microsoft 7.2k Dec 30, 2022
Jellyfin Desktop Client based on Plex Media Player

Jellyfin Media Player Based on (but not affiliated with) Plex Media Player. Please see: Corresponding web client: Repo Release API Docs in client-api.

Ian Walton 1.3k Dec 27, 2022
Qt Based WhatsApp Client

WhatSie WhatSie is Light, feature rich WhatsApp web client written in Qt and not on Electron. A simple & beautiful desktop client for WhatsApp Web. Ch

Keshav Bhatt 691 Dec 27, 2022
A VPN client for Android based on OpenVPN made with Jetpack Compose.

Gear VPN - Free, Secure & Open sourced VPN Tech Stack Jetpack Compose - Google's new UI toolkit for developing native Android apps. Navigator-Compose

Kaustubh Patange 86 Dec 23, 2022
A GlobalProtect VPN client (GUI) for Linux based on OpenConnect and built with Qt5, supports SAML auth mode.

A GlobalProtect VPN client (GUI) for Linux based on OpenConnect and built with Qt5, supports SAML auth mode.

Kevin Yue 603 Jan 2, 2023
A Lightweight and fully asynchronous WebSocket client library based on libev

libuwsc(中文) A Lightweight and fully asynchronous WebSocket client library based on libev for Embedded Linux. And provide Lua-binding. Why should I cho

Jianhui Zhao 285 Dec 24, 2022
An unofficial Qt-based client for Telegram messenger.

Kutegram How to build Symbian^1 (also Symbian^3) Clone this repository with submodules. git clone --recursive https://github.com/kutegram/client.git c

Kutegram 18 Sep 22, 2022
An SFTP client shared library (dll/so/dylib) with bindings and classes for C++, Delphi and Free Pascal based on PuTTY

TGPuttyLib A shared library / DLL with Delphi and C++ bindings based on PuTTY, for Windows, macOS, and Linux. The new TGPuttyLib SFTP Library is a DLL

Tobias Giesen 74 Dec 19, 2022
A C++ header-only HTTP/HTTPS server and client library

cpp-httplib A C++11 single-file header-only cross platform HTTP/HTTPS library. It's extremely easy to setup. Just include the httplib.h file in your c

null 8.3k Dec 31, 2022
Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution

CppServer Ultra fast and low latency asynchronous socket server & client C++ library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and

Ivan Shynkarenka 958 Jan 3, 2023