From 32a0742d08fa5570f34db0ffe4bd84a5525b5f64 Mon Sep 17 00:00:00 2001 From: Jasper Hugo Date: Mon, 7 Mar 2022 17:38:41 +0700 Subject: [PATCH] Automatically determine xmpp-domain if not specified, update README --- README.md | 11 ++------- gst-meet/src/main.rs | 58 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index a7c5875..4ea60fa 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # gst-meet: Integrate Jitsi Meet conferences with GStreamer pipelines -Note: gst-meet is in an **alpha** state and is under active development. The command-line options and the lib-gst-meet API are subject to change, and some important features (simulcast, RTX, TCC) are not yet fully functional. +Note: gst-meet is in an **alpha** state and is under active development. The command-line options and the lib-gst-meet API are subject to change. gst-meet provides a library and tool for integrating Jitsi Meet conferences with GStreamer pipelines. You can pipe audio and video into a conference as a participant, and pipe out other participants' audio and video streams. @@ -42,7 +42,7 @@ You can pass two different pipeline fragments to gst-meet. `--send-pipeline` is for sending audio and video. If it contains an element named `audio`, this audio will be streamed to the conference. The audio codec must be 48kHz Opus. If it contains an element named `video`, this video will be streamed to the conference. The video codec must match the codec passed to `--video-codec`, which is VP8 by default. -`--recv-pipeline-participant-template` is for receiving audio and video from other participants. This pipeline will be created once for each other participant in the conference. If it contains an element named `audio`, the participant's audio (48kHz Opus) will be sent to that element. If it contains an element named `video`, the participant's video (encoded with the codec selected by `--video-codec`) will be sent to that element. The strings `{jid}`, `{jid_user}`, `{participant_id}` and `{nick}` are replaced in the template with the participant's full JID, user part, MUC JID resource part (a.k.a. participant/occupant ID) and nickname respectively. +`--recv-pipeline-participant-template` is for receiving audio and video from other participants. This pipeline will be created once for each other participant in the conference. If it contains an element named `audio`, the participant's audio (48kHz Opus) will be sent to that element. If it contains an element named `video`, the participant's video will be sent to that element. The strings `{jid}`, `{jid_user}`, `{participant_id}` and `{nick}` are replaced in the template with the participant's full JID, user part, MUC JID resource part (a.k.a. participant/occupant ID) and nickname respectively. ## Examples @@ -54,7 +54,6 @@ Stream an Opus audio file to the conference. This is very efficient; the Opus da ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --send-pipeline="filesrc location=sample.opus ! queue ! oggdemux name=audio" ``` @@ -63,7 +62,6 @@ Stream a FLAC audio file to the conference, transcoding it to Opus: ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --send-pipeline="filesrc location=shake-it-off.flac ! queue ! flacdec ! audioconvert ! audioresample ! opusenc name=audio" ``` @@ -72,7 +70,6 @@ Stream a .webm file containing VP8 video and Vorbis audio to the conference. Thi ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --send-pipeline="filesrc location=big-buck-bunny_trailer.webm ! queue ! matroskademux name=demuxer demuxer.video_0 ! queue name=video @@ -83,7 +80,6 @@ Stream the default video & audio inputs to the conference, encoding as VP8 and O ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --send-pipeline="autovideosrc ! queue ! videoconvert ! vp8enc buffer-size=1000 deadline=1 name=video autoaudiosrc ! queue ! audioconvert ! audioresample ! opusenc name=audio" \ @@ -95,7 +91,6 @@ Record a .webm file for each other participant, containing VP8 video and Opus au ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm opusparse name=audio ! muxer.audio_0 @@ -106,7 +101,6 @@ The above .webm file unfortunately may not play in most players, because the res ``` gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm opusparse name=audio ! muxer.audio_0 @@ -118,7 +112,6 @@ Play a YouTube video in the conference. By requesting Opus audio and VP9 video f ``` YOUTUBE_URL="https://www.youtube.com/watch?v=vjV_2Ri2rfE" gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ - --xmpp-domain=your.jitsi.domain \ --room-name=roomname \ --video-codec=vp9 \ --send-pipeline="curlhttpsrc location=\"$(youtube-dl -g $YOUTUBE_URL -f 'bestaudio[acodec=opus]')\" ! queue ! matroskademux name=audiodemux diff --git a/gst-meet/src/main.rs b/gst-meet/src/main.rs index a438ac4..e6cf9ba 100644 --- a/gst-meet/src/main.rs +++ b/gst-meet/src/main.rs @@ -9,6 +9,7 @@ use gstreamer::{ prelude::{ElementExt, GstBinExt}, GhostPad, }; +use http::Uri; use lib_gst_meet::{ init_tracing, Authentication, Connection, JitsiConference, JitsiConferenceConfig, MediaType, }; @@ -24,15 +25,28 @@ use tracing::{error, info, trace, warn}; struct Opt { #[structopt(long)] web_socket_url: String, - #[structopt(long)] - xmpp_domain: String, + #[structopt( + long, + help = "If not specified, assumed to be the host part of ", + )] + xmpp_domain: Option, #[structopt(long)] room_name: String, - #[structopt(long)] + #[structopt( + long, + help = "If not specified, assumed to be conference.", + )] muc_domain: Option, - #[structopt(long)] + #[structopt( + long, + help = "If not specified, assumed to be focus@auth./focus", + )] focus_jid: Option, - #[structopt(long, default_value = "vp8")] + #[structopt( + long, + default_value = "vp8", + help = "The video codec to negotiate support for. One of: vp8, vp9, h264", + )] video_codec: String, #[structopt(long, default_value = "gst-meet")] nick: String, @@ -42,13 +56,25 @@ struct Opt { send_pipeline: Option, #[structopt(long)] recv_pipeline_participant_template: Option, - #[structopt(long)] + #[structopt( + long, + help = "Comma-separated endpoint IDs to select (prioritise receiving of)", + )] select_endpoints: Option, - #[structopt(long)] + #[structopt( + long, + help = "The maximum number of video streams we would like to receive", + )] last_n: Option, - #[structopt(long)] + #[structopt( + long, + help = "The maximum height to receive video at." + )] recv_video_height: Option, - #[structopt(long)] + #[structopt( + long, + help = "The video type to signal that we are sending. One of: camera, desktop" + )] video_type: Option, #[structopt(long)] start_bitrate: Option, @@ -128,10 +154,18 @@ async fn main_inner() -> Result<()> { .map(|pipeline| gstreamer::parse_bin_from_description(pipeline, false)) .transpose() .context("failed to parse send pipeline")?; + + let web_socket_url: Uri = opt.web_socket_url.parse()?; + + let xmpp_domain = opt + .xmpp_domain + .as_deref() + .or_else(|| web_socket_url.host()) + .context("invalid WebSocket URL")?; let (connection, background) = Connection::new( &opt.web_socket_url, - &opt.xmpp_domain, + xmpp_domain, Authentication::Anonymous, #[cfg(feature = "tls-insecure")] opt.tls_insecure, @@ -151,13 +185,13 @@ async fn main_inner() -> Result<()> { opt .muc_domain .clone() - .unwrap_or_else(|| { format!("conference.{}", opt.xmpp_domain) }), + .unwrap_or_else(|| { format!("conference.{}", xmpp_domain) }), ); let focus_jid = opt .focus_jid .clone() - .unwrap_or_else(|| format!("focus@auth.{}/focus", opt.xmpp_domain,)); + .unwrap_or_else(|| format!("focus@auth.{}/focus", xmpp_domain)); let Opt { nick,