Automatically determine xmpp-domain if not specified, update README

This commit is contained in:
Jasper Hugo 2022-03-07 17:38:41 +07:00
parent ca8cca9393
commit 32a0742d08
2 changed files with 48 additions and 21 deletions

View File

@ -1,6 +1,6 @@
# gst-meet: Integrate Jitsi Meet conferences with GStreamer pipelines # 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. 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. `--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 ## 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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--send-pipeline="filesrc location=sample.opus ! queue ! oggdemux name=audio" --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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--send-pipeline="filesrc location=shake-it-off.flac ! queue ! flacdec ! audioconvert ! audioresample ! opusenc name=audio" --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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--send-pipeline="filesrc location=big-buck-bunny_trailer.webm ! queue ! matroskademux name=demuxer --send-pipeline="filesrc location=big-buck-bunny_trailer.webm ! queue ! matroskademux name=demuxer
demuxer.video_0 ! queue name=video 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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--send-pipeline="autovideosrc ! queue ! videoconvert ! vp8enc buffer-size=1000 deadline=1 name=video --send-pipeline="autovideosrc ! queue ! videoconvert ! vp8enc buffer-size=1000 deadline=1 name=video
autoaudiosrc ! queue ! audioconvert ! audioresample ! opusenc name=audio" \ 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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm --recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm
opusparse name=audio ! muxer.audio_0 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 \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm --recv-pipeline-participant-template="webmmux name=muxer ! filesink location={participant_id}.webm
opusparse name=audio ! muxer.audio_0 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" YOUTUBE_URL="https://www.youtube.com/watch?v=vjV_2Ri2rfE"
gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \ gst-meet --web-socket-url=wss://your.jitsi.domain/xmpp-websocket \
--xmpp-domain=your.jitsi.domain \
--room-name=roomname \ --room-name=roomname \
--video-codec=vp9 \ --video-codec=vp9 \
--send-pipeline="curlhttpsrc location=\"$(youtube-dl -g $YOUTUBE_URL -f 'bestaudio[acodec=opus]')\" ! queue ! matroskademux name=audiodemux --send-pipeline="curlhttpsrc location=\"$(youtube-dl -g $YOUTUBE_URL -f 'bestaudio[acodec=opus]')\" ! queue ! matroskademux name=audiodemux

View File

@ -9,6 +9,7 @@ use gstreamer::{
prelude::{ElementExt, GstBinExt}, prelude::{ElementExt, GstBinExt},
GhostPad, GhostPad,
}; };
use http::Uri;
use lib_gst_meet::{ use lib_gst_meet::{
init_tracing, Authentication, Connection, JitsiConference, JitsiConferenceConfig, MediaType, init_tracing, Authentication, Connection, JitsiConference, JitsiConferenceConfig, MediaType,
}; };
@ -24,15 +25,28 @@ use tracing::{error, info, trace, warn};
struct Opt { struct Opt {
#[structopt(long)] #[structopt(long)]
web_socket_url: String, web_socket_url: String,
#[structopt(long)] #[structopt(
xmpp_domain: String, long,
help = "If not specified, assumed to be the host part of <web-socket-url>",
)]
xmpp_domain: Option<String>,
#[structopt(long)] #[structopt(long)]
room_name: String, room_name: String,
#[structopt(long)] #[structopt(
long,
help = "If not specified, assumed to be conference.<xmpp-domain>",
)]
muc_domain: Option<String>, muc_domain: Option<String>,
#[structopt(long)] #[structopt(
long,
help = "If not specified, assumed to be focus@auth.<xmpp-domain>/focus",
)]
focus_jid: Option<String>, focus_jid: Option<String>,
#[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, video_codec: String,
#[structopt(long, default_value = "gst-meet")] #[structopt(long, default_value = "gst-meet")]
nick: String, nick: String,
@ -42,13 +56,25 @@ struct Opt {
send_pipeline: Option<String>, send_pipeline: Option<String>,
#[structopt(long)] #[structopt(long)]
recv_pipeline_participant_template: Option<String>, recv_pipeline_participant_template: Option<String>,
#[structopt(long)] #[structopt(
long,
help = "Comma-separated endpoint IDs to select (prioritise receiving of)",
)]
select_endpoints: Option<String>, select_endpoints: Option<String>,
#[structopt(long)] #[structopt(
long,
help = "The maximum number of video streams we would like to receive",
)]
last_n: Option<u16>, last_n: Option<u16>,
#[structopt(long)] #[structopt(
long,
help = "The maximum height to receive video at."
)]
recv_video_height: Option<u16>, recv_video_height: Option<u16>,
#[structopt(long)] #[structopt(
long,
help = "The video type to signal that we are sending. One of: camera, desktop"
)]
video_type: Option<String>, video_type: Option<String>,
#[structopt(long)] #[structopt(long)]
start_bitrate: Option<u32>, start_bitrate: Option<u32>,
@ -128,10 +154,18 @@ async fn main_inner() -> Result<()> {
.map(|pipeline| gstreamer::parse_bin_from_description(pipeline, false)) .map(|pipeline| gstreamer::parse_bin_from_description(pipeline, false))
.transpose() .transpose()
.context("failed to parse send pipeline")?; .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( let (connection, background) = Connection::new(
&opt.web_socket_url, &opt.web_socket_url,
&opt.xmpp_domain, xmpp_domain,
Authentication::Anonymous, Authentication::Anonymous,
#[cfg(feature = "tls-insecure")] #[cfg(feature = "tls-insecure")]
opt.tls_insecure, opt.tls_insecure,
@ -151,13 +185,13 @@ async fn main_inner() -> Result<()> {
opt opt
.muc_domain .muc_domain
.clone() .clone()
.unwrap_or_else(|| { format!("conference.{}", opt.xmpp_domain) }), .unwrap_or_else(|| { format!("conference.{}", xmpp_domain) }),
); );
let focus_jid = opt let focus_jid = opt
.focus_jid .focus_jid
.clone() .clone()
.unwrap_or_else(|| format!("focus@auth.{}/focus", opt.xmpp_domain,)); .unwrap_or_else(|| format!("focus@auth.{}/focus", xmpp_domain));
let Opt { let Opt {
nick, nick,