snapshot of https://github.com/jitsi/jibri.git @ 3b45602c539ec69d128ea152ae587d0b6582191a (2026-09-15)
This commit is contained in:
238
doc/local-run/run-jibri-local.sh
Executable file
238
doc/local-run/run-jibri-local.sh
Executable file
@@ -0,0 +1,238 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Generate a jibri.conf from a docker-jitsi-meet .env and run jibri from
|
||||
# this source tree, connecting it to the running docker deployment.
|
||||
#
|
||||
# Defaults:
|
||||
# JIBRI_DIR -> repo root (resolved from this script's location)
|
||||
# DOCKER_JITSI_DIR -> $HOME/dev/docker-jitsi-meet
|
||||
#
|
||||
# Pre-req: prosody port 5222 must be reachable from the host. The default
|
||||
# docker-jitsi-meet compose only `expose:`s it, so apply prosody.override.yml
|
||||
# from this directory:
|
||||
#
|
||||
# docker compose -f docker-compose.yml \
|
||||
# -f /path/to/jibri/doc/local-run/prosody.override.yml up -d
|
||||
#
|
||||
# See README.md alongside this script for a full walkthrough.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
JIBRI_DIR="${JIBRI_DIR:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
|
||||
DOCKER_JITSI_DIR="${DOCKER_JITSI_DIR:-$HOME/dev/docker-jitsi-meet}"
|
||||
ENV_FILE="$DOCKER_JITSI_DIR/.env"
|
||||
|
||||
[ -f "$ENV_FILE" ] || { echo "missing $ENV_FILE (set DOCKER_JITSI_DIR)" >&2; exit 1; }
|
||||
[ -d "$JIBRI_DIR" ] || { echo "missing $JIBRI_DIR" >&2; exit 1; }
|
||||
|
||||
set -a
|
||||
# shellcheck disable=SC1090
|
||||
. "$ENV_FILE"
|
||||
set +a
|
||||
|
||||
# Defaults match jibri/rootfs/defaults/xmpp.conf and jibri.conf templates.
|
||||
XMPP_DOMAIN="${XMPP_DOMAIN:-meet.jitsi}"
|
||||
XMPP_AUTH_DOMAIN="${XMPP_AUTH_DOMAIN:-auth.meet.jitsi}"
|
||||
XMPP_INTERNAL_MUC_DOMAIN="${XMPP_INTERNAL_MUC_DOMAIN:-internal-muc.meet.jitsi}"
|
||||
XMPP_HIDDEN_DOMAIN="${XMPP_HIDDEN_DOMAIN:-hidden.meet.jitsi}"
|
||||
XMPP_MUC_DOMAIN="${XMPP_MUC_DOMAIN:-muc.meet.jitsi}"
|
||||
JIBRI_BREWERY_MUC="${JIBRI_BREWERY_MUC:-jibribrewery}"
|
||||
JIBRI_RECORDER_USER="${JIBRI_RECORDER_USER:-recorder}"
|
||||
JIBRI_XMPP_USER="${JIBRI_XMPP_USER:-jibri}"
|
||||
JIBRI_USAGE_TIMEOUT="${JIBRI_USAGE_TIMEOUT:-0}"
|
||||
XMPP_PORT="${XMPP_PORT:-5222}"
|
||||
XMPP_HOST="${XMPP_HOST:-127.0.0.1}"
|
||||
JIBRI_RECORDING_RESOLUTION="${JIBRI_RECORDING_RESOLUTION:-1280x720}"
|
||||
JIBRI_AUDIO_SOURCE="${JIBRI_AUDIO_SOURCE:-alsa}"
|
||||
JIBRI_AUDIO_DEVICE="${JIBRI_AUDIO_DEVICE:-plug:bsnoop}"
|
||||
# macOS only: avfoundation device indices for screen + audio capture.
|
||||
# Find them with: ffmpeg -f avfoundation -list_devices true -i ""
|
||||
# When unset, jibri's default input ("0:0", usually camera + mic) is used.
|
||||
JIBRI_MAC_VIDEO_DEVICE="${JIBRI_MAC_VIDEO_DEVICE:-}"
|
||||
JIBRI_MAC_AUDIO_DEVICE="${JIBRI_MAC_AUDIO_DEVICE:-}"
|
||||
JIBRI_INSTANCE_ID="${JIBRI_INSTANCE_ID:-jibri-local-$$}"
|
||||
JIBRI_STRIP_DOMAIN_JID="${JIBRI_STRIP_DOMAIN_JID:-${XMPP_MUC_DOMAIN%%.*}}"
|
||||
|
||||
: "${JIBRI_XMPP_PASSWORD:?JIBRI_XMPP_PASSWORD not set in .env (run gen-passwords.sh)}"
|
||||
: "${JIBRI_RECORDER_PASSWORD:?JIBRI_RECORDER_PASSWORD not set in .env}"
|
||||
|
||||
BASE_URL_LINE=""
|
||||
[ -n "${PUBLIC_URL:-}" ] && BASE_URL_LINE=" base-url = \"$PUBLIC_URL\""
|
||||
|
||||
WORKDIR="$JIBRI_DIR/.local"
|
||||
JIBRI_CONF="$WORKDIR/jibri.conf"
|
||||
LOGGING="$WORKDIR/logging.properties"
|
||||
RECORDINGS="$WORKDIR/recordings"
|
||||
mkdir -p "$WORKDIR" "$RECORDINGS"
|
||||
|
||||
# Probe prosody on the host before generating config / starting jibri.
|
||||
# Run the /dev/tcp probe in a subshell so neither fd 3 nor stderr leak back here.
|
||||
if ! (exec 3<>"/dev/tcp/$XMPP_HOST/$XMPP_PORT") 2>/dev/null; then
|
||||
cat >&2 <<EOF
|
||||
cannot reach prosody at $XMPP_HOST:$XMPP_PORT.
|
||||
|
||||
The default compose only exposes 5222 inside the docker network. Apply the
|
||||
override shipped next to this script and restart:
|
||||
|
||||
docker compose -f docker-compose.yml -f $SCRIPT_DIR/prosody.override.yml up -d
|
||||
EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# macOS screen capture: avfoundation's screen devices only deliver the native
|
||||
# (retina) resolution, so drop -video_size from the input and scale on the
|
||||
# encoder side instead.
|
||||
FFMPEG_MAC_OVERRIDES=""
|
||||
if [ -n "$JIBRI_MAC_VIDEO_DEVICE" ]; then
|
||||
[ -n "$JIBRI_MAC_AUDIO_DEVICE" ] || {
|
||||
echo "JIBRI_MAC_VIDEO_DEVICE is set but JIBRI_MAC_AUDIO_DEVICE is not (pick one from: ffmpeg -f avfoundation -list_devices true -i \"\")" >&2
|
||||
exit 1
|
||||
}
|
||||
FFMPEG_MAC_OVERRIDES=$(cat <<EOG
|
||||
input-mac = [
|
||||
"-thread_queue_size", "4096",
|
||||
"-f", "avfoundation",
|
||||
"-capture_cursor", "0",
|
||||
"-framerate", "30",
|
||||
"-i", "$JIBRI_MAC_VIDEO_DEVICE:$JIBRI_MAC_AUDIO_DEVICE"
|
||||
]
|
||||
video-params = [
|
||||
"-vf", "scale=${JIBRI_RECORDING_RESOLUTION%%x*}:-2",
|
||||
"-c:v", "libx264",
|
||||
"-pix_fmt", "yuv420p",
|
||||
"-r", "30",
|
||||
"-crf", "25"
|
||||
]
|
||||
EOG
|
||||
)
|
||||
fi
|
||||
|
||||
FFMPEG_LINUX_OVERRIDES=$(cat <<EOG
|
||||
input-linux = [
|
||||
"-f", "x11grab",
|
||||
"-i", "${DISPLAY:-:0}",
|
||||
]
|
||||
EOG
|
||||
)
|
||||
|
||||
cat > "$JIBRI_CONF" <<EOF
|
||||
jibri {
|
||||
id = "$JIBRI_INSTANCE_ID"
|
||||
single-use-mode = false
|
||||
|
||||
recording {
|
||||
recordings-directory = "$RECORDINGS"
|
||||
finalize-script = "$JIBRI_DIR/resources/finalize_recording.sh"
|
||||
}
|
||||
|
||||
ffmpeg {
|
||||
resolution = "$JIBRI_RECORDING_RESOLUTION"
|
||||
audio-source = "$JIBRI_AUDIO_SOURCE"
|
||||
audio-device = "$JIBRI_AUDIO_DEVICE"
|
||||
$FFMPEG_MAC_OVERRIDES
|
||||
$FFMPEG_LINUX_OVERRIDES
|
||||
}
|
||||
|
||||
chrome {
|
||||
flags = [
|
||||
"--use-fake-ui-for-media-stream",
|
||||
"--enabled",
|
||||
"--autoplay-policy=no-user-gesture-required",
|
||||
"--ignore-certificate-errors",
|
||||
"--ozone-platform=x11" # Force X11, required for x11grab to capture video
|
||||
]
|
||||
}
|
||||
|
||||
stats {
|
||||
prometheus.enabled = false
|
||||
}
|
||||
|
||||
api {
|
||||
xmpp {
|
||||
environments = [
|
||||
{
|
||||
name = "docker-local"
|
||||
xmpp-server-hosts = ["$XMPP_HOST"]
|
||||
xmpp-domain = "$XMPP_DOMAIN"
|
||||
$BASE_URL_LINE
|
||||
|
||||
control-muc {
|
||||
domain = "$XMPP_INTERNAL_MUC_DOMAIN"
|
||||
room-name = "$JIBRI_BREWERY_MUC"
|
||||
nickname = "$JIBRI_INSTANCE_ID"
|
||||
}
|
||||
|
||||
control-login {
|
||||
domain = "$XMPP_AUTH_DOMAIN"
|
||||
port = "$XMPP_PORT"
|
||||
username = "$JIBRI_XMPP_USER"
|
||||
password = "$JIBRI_XMPP_PASSWORD"
|
||||
}
|
||||
|
||||
call-login {
|
||||
domain = "$XMPP_HIDDEN_DOMAIN"
|
||||
username = "$JIBRI_RECORDER_USER"
|
||||
password = "$JIBRI_RECORDER_PASSWORD"
|
||||
}
|
||||
|
||||
strip-from-room-domain = "$JIBRI_STRIP_DOMAIN_JID."
|
||||
usage-timeout = "$JIBRI_USAGE_TIMEOUT"
|
||||
trust-all-xmpp-certs = true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
# Console-only logging. Root .level must allow FINE through to the handler.
|
||||
cat > "$LOGGING" <<EOF
|
||||
handlers = java.util.logging.ConsoleHandler
|
||||
|
||||
.level = FINE
|
||||
|
||||
java.util.logging.ConsoleHandler.level = FINE
|
||||
java.util.logging.ConsoleHandler.formatter = org.jitsi.utils.logging2.JitsiLogFormatter
|
||||
|
||||
# ffmpeg/browser are attached to dedicated JUL loggers with parent propagation
|
||||
# disabled, so their output never reaches the console. Pin their FileHandlers
|
||||
# to the workdir so we can read them.
|
||||
org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.pattern = $WORKDIR/ffmpeg.%g.txt
|
||||
org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.formatter = org.jitsi.utils.logging2.JitsiLogFormatter
|
||||
org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.limit = 10000000
|
||||
org.jitsi.jibri.capture.ffmpeg.util.FfmpegFileHandler.count = 5
|
||||
|
||||
org.jitsi.jibri.selenium.util.BrowserFileHandler.pattern = $WORKDIR/browser.%g.txt
|
||||
org.jitsi.jibri.selenium.util.BrowserFileHandler.formatter = org.jitsi.utils.logging2.JitsiLogFormatter
|
||||
org.jitsi.jibri.selenium.util.BrowserFileHandler.limit = 10000000
|
||||
org.jitsi.jibri.selenium.util.BrowserFileHandler.count = 5
|
||||
|
||||
org.jitsi.level = FINE
|
||||
org.jitsi.jibri.config.level = INFO
|
||||
org.glassfish.level = INFO
|
||||
jdk.internal.net.http.level = INFO
|
||||
EOF
|
||||
|
||||
JAR="$(ls -t "$JIBRI_DIR"/target/jibri-*-jar-with-dependencies.jar 2>/dev/null | head -n1 || true)"
|
||||
if [ -z "$JAR" ]; then
|
||||
echo "building jibri..."
|
||||
(cd "$JIBRI_DIR" && mvn -B -DskipTests clean package)
|
||||
JAR="$(ls -t "$JIBRI_DIR"/target/jibri-*-jar-with-dependencies.jar | head -n1)"
|
||||
fi
|
||||
|
||||
CHROMEDRIVER="${CHROMEDRIVER:-$JIBRI_DIR/chromedriver}"
|
||||
[ -x "$CHROMEDRIVER" ] || { echo "missing chromedriver at $CHROMEDRIVER" >&2; exit 1; }
|
||||
|
||||
echo "config: $JIBRI_CONF"
|
||||
echo "jar: $JAR"
|
||||
echo "chromedriver: $CHROMEDRIVER"
|
||||
echo "xmpp: $XMPP_HOST:$XMPP_PORT (domain=$XMPP_DOMAIN)"
|
||||
echo
|
||||
|
||||
exec java \
|
||||
-Djava.util.logging.config.file="$LOGGING" \
|
||||
-Dconfig.file="$JIBRI_CONF" \
|
||||
-Dwebdriver.chrome.driver="$CHROMEDRIVER" \
|
||||
-Dwebdriver.chrome.logfile="$WORKDIR/chromedriver.log" \
|
||||
-jar "$JAR"
|
||||
Reference in New Issue
Block a user