Proxy: Add ffmpeg-from-source builder; auto-fallback in SRT E2E test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7b8981d8b9
commit
d1fc8c1253
|
|
@ -346,13 +346,14 @@ How to verify SRS works correctly.
|
|||
- Reconnecting Load Test
|
||||
- Janus
|
||||
|
||||
`.openclaw/skills/srs-develop/scripts/` — Go proxy verification scripts:
|
||||
`.openclaw/skills/srs-develop/scripts/` — Go proxy verification and setup scripts:
|
||||
- `proxy-utest.sh` — Runs Go proxy unit tests with optional coverage.
|
||||
- `proxy-e2e-test.sh` — Single-origin RTMP proxy E2E test.
|
||||
- `proxy-e2e-cluster-test.sh` — Multi-origin memory load-balancer E2E test.
|
||||
- `proxy-e2e-redis-test.sh` — Multi-proxy Redis load-balancer E2E test.
|
||||
- `proxy-e2e-transmux-test.sh` — RTMP publish through proxy, then verify RTMP, HTTP-FLV, HLS, and WebRTC playback.
|
||||
- `proxy-e2e-srt-test.sh` — SRT publish through proxy, then verify SRT, RTMP, HTTP-FLV, and HLS playback (WebRTC WHEP is a placeholder).
|
||||
- `setup-ffmpeg-with-whip.sh` — macOS-only: build ffmpeg from source into `~/.local/` with WHIP (openssl DTLS) and SRT support; auto-invoked by `proxy-e2e-srt-test.sh` when no SRT-capable ffmpeg is found.
|
||||
|
||||
**Summary: The Key Differences**
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ probe_has_audio_video() {
|
|||
|
||||
echo "Verifying $name playback: $url"
|
||||
local output
|
||||
output=$(ffprobe -v error -show_streams "$url" 2>&1 || true)
|
||||
output=$("$FFPROBE_BIN" -v error -show_streams "$url" 2>&1 || true)
|
||||
|
||||
if echo "$output" | grep -q "codec_type=video"; then
|
||||
echo "PASS: $name video stream detected."
|
||||
|
|
@ -121,33 +121,59 @@ if [[ ! -f "$SOURCE_FLV" ]]; then
|
|||
echo "Error: test source not found: $SOURCE_FLV" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v ffmpeg &>/dev/null; then
|
||||
echo "Error: ffmpeg not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v ffprobe &>/dev/null; then
|
||||
echo "Error: ffprobe not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! command -v curl &>/dev/null; then
|
||||
echo "Error: curl not found in PATH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# SRT URLs need libsrt compiled into ffmpeg/ffprobe. The default Homebrew
|
||||
# ffmpeg formula does NOT include libsrt — install the homebrew-ffmpeg tap
|
||||
# build with the explicit --with-srt option instead:
|
||||
# brew tap homebrew-ffmpeg/ffmpeg
|
||||
# brew uninstall ffmpeg # if vanilla ffmpeg is already installed
|
||||
# brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-srt
|
||||
if ! ffmpeg -hide_banner -protocols 2>/dev/null | grep -qw srt; then
|
||||
echo "Error: ffmpeg was built without SRT protocol support." >&2
|
||||
echo "The default 'brew install ffmpeg' does NOT include libsrt." >&2
|
||||
echo "Install the homebrew-ffmpeg tap build with --with-srt instead:" >&2
|
||||
echo " brew tap homebrew-ffmpeg/ffmpeg" >&2
|
||||
echo " brew uninstall ffmpeg # if vanilla ffmpeg is already installed" >&2
|
||||
echo " brew install homebrew-ffmpeg/ffmpeg/ffmpeg --with-srt" >&2
|
||||
exit 1
|
||||
# ffmpeg formula does NOT include libsrt. Resolution order:
|
||||
# 1. Use ffmpeg/ffprobe from PATH if they support SRT.
|
||||
# 2. Otherwise, use ~/.local/bin/ffmpeg/ffprobe if previously built there.
|
||||
# 3. Otherwise, build from source via setup-ffmpeg-with-whip.sh (installs
|
||||
# into ~/.local/) and use the freshly built binaries.
|
||||
ffmpeg_has_srt() {
|
||||
local bin="$1"
|
||||
[[ -x "$bin" ]] && "$bin" -hide_banner -protocols 2>/dev/null | grep -qw srt
|
||||
}
|
||||
|
||||
resolve_ffmpeg() {
|
||||
local sys_ffmpeg sys_ffprobe local_ffmpeg local_ffprobe
|
||||
sys_ffmpeg="$(command -v ffmpeg || true)"
|
||||
sys_ffprobe="$(command -v ffprobe || true)"
|
||||
local_ffmpeg="$HOME/.local/bin/ffmpeg"
|
||||
local_ffprobe="$HOME/.local/bin/ffprobe"
|
||||
|
||||
if [[ -n "$sys_ffprobe" ]] && ffmpeg_has_srt "$sys_ffmpeg"; then
|
||||
FFMPEG_BIN="$sys_ffmpeg"
|
||||
FFPROBE_BIN="$sys_ffprobe"
|
||||
return 0
|
||||
fi
|
||||
if [[ -x "$local_ffprobe" ]] && ffmpeg_has_srt "$local_ffmpeg"; then
|
||||
FFMPEG_BIN="$local_ffmpeg"
|
||||
FFPROBE_BIN="$local_ffprobe"
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
if ! resolve_ffmpeg; then
|
||||
echo "No ffmpeg with SRT support found on PATH or in ~/.local/bin."
|
||||
echo "Building ffmpeg from source via setup-ffmpeg-with-whip.sh — this can take several minutes."
|
||||
bash "$SCRIPT_DIR/setup-ffmpeg-with-whip.sh"
|
||||
FFMPEG_BIN="$HOME/.local/bin/ffmpeg"
|
||||
FFPROBE_BIN="$HOME/.local/bin/ffprobe"
|
||||
if ! ffmpeg_has_srt "$FFMPEG_BIN"; then
|
||||
echo "Error: ffmpeg still lacks SRT support after running setup-ffmpeg-with-whip.sh." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -x "$FFPROBE_BIN" ]]; then
|
||||
echo "Error: ffprobe missing at $FFPROBE_BIN after running setup-ffmpeg-with-whip.sh." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "ffmpeg : $FFMPEG_BIN"
|
||||
echo "ffprobe: $FFPROBE_BIN"
|
||||
|
||||
# --- Step 0: Clean up stale state ---
|
||||
rm -f "$WORKSPACE/trunk/objs/origin1.pid"
|
||||
|
|
@ -217,7 +243,7 @@ echo "SRS origin started and registered."
|
|||
# --- Step 5: Publish SRT stream ---
|
||||
echo "=== Step 5: Publishing SRT stream to proxy ==="
|
||||
echo "Publish URL: $SRT_PUBLISH_URL"
|
||||
ffmpeg -stream_loop -1 -re -i "$SOURCE_FLV" -c copy -f mpegts \
|
||||
"$FFMPEG_BIN" -stream_loop -1 -re -i "$SOURCE_FLV" -c copy -f mpegts \
|
||||
"$SRT_PUBLISH_URL" >/tmp/srs-ffmpeg-srt-e2e.log 2>&1 &
|
||||
FFMPEG_PID=$!
|
||||
echo "FFmpeg publisher PID: $FFMPEG_PID"
|
||||
|
|
|
|||
232
.openclaw/skills/srs-develop/scripts/setup-ffmpeg-with-whip.sh
Executable file
232
.openclaw/skills/srs-develop/scripts/setup-ffmpeg-with-whip.sh
Executable file
|
|
@ -0,0 +1,232 @@
|
|||
#!/bin/bash
|
||||
# Build ffmpeg from source with the codecs and protocols the SRS proxy E2E
|
||||
# tests need — in particular WHIP (WebRTC-HTTP Ingestion Protocol), which the
|
||||
# default Homebrew formulas (vanilla + homebrew-ffmpeg tap) do not enable.
|
||||
#
|
||||
# Modelled on the ossrs/dev-docker ubuntu20 base images:
|
||||
# https://github.com/ossrs/dev-docker/blob/ubuntu20/Dockerfile.base
|
||||
# https://github.com/ossrs/dev-docker/blob/ubuntu20/Dockerfile.base2
|
||||
# https://github.com/ossrs/dev-docker/blob/ubuntu20/Dockerfile.base3
|
||||
# The Dockerfiles describe *which* libraries and configure flags to enable;
|
||||
# on macOS we install those deps via Homebrew (shared libs) instead of
|
||||
# rebuilding each one from tarballs. ffmpeg itself is built from source so we
|
||||
# can pass --enable-libsrtp / --enable-openssl, which neither Homebrew formula
|
||||
# turns on.
|
||||
#
|
||||
# Output:
|
||||
# ~/.local/src/ffmpeg (git clone)
|
||||
# ~/.local/bin/{ffmpeg,ffprobe,ffplay}
|
||||
# ~/.local/lib, ~/.local/share, ... (ffmpeg --prefix tree)
|
||||
#
|
||||
# Re-running is safe: deps already installed are skipped, the git clone is
|
||||
# reused (fetch + checkout), and ffmpeg is rebuilt incrementally.
|
||||
set -e
|
||||
|
||||
FFMPEG_TAG="${FFMPEG_TAG:-n8.1.1}"
|
||||
PREFIX="${PREFIX:-$HOME/.local}"
|
||||
SRC_DIR="${SRC_DIR:-$HOME/.local/src/ffmpeg}"
|
||||
JOBS="${JOBS:-$(sysctl -n hw.ncpu 2>/dev/null || echo 4)}"
|
||||
|
||||
REQUIRED_BREW_PKGS=(
|
||||
# build toolchain (Homebrew renamed pkg-config → pkgconf in 2024)
|
||||
pkgconf nasm
|
||||
# WHIP needs DTLS (openssl). ffmpeg's WHIP muxer uses ffmpeg's *internal*
|
||||
# SRTP implementation (srtp_protocol_select="rtp_protocol srtp" in configure)
|
||||
# — no external libsrtp dependency, so no extra brew package here.
|
||||
openssl@3
|
||||
# SRT
|
||||
srt
|
||||
# video codecs (matches Dockerfile.base / .base2)
|
||||
x264 x265 libvpx
|
||||
# audio codecs (fdk-aac requires --enable-nonfree below)
|
||||
fdk-aac lame opus
|
||||
# subtitle / font stack (matches Dockerfile.base3)
|
||||
freetype fontconfig harfbuzz fribidi libass
|
||||
)
|
||||
|
||||
log() { printf '\n=== %s ===\n' "$*"; }
|
||||
|
||||
# --- Pre-checks ---------------------------------------------------------------
|
||||
|
||||
if [[ "$(uname -s)" != "Darwin" ]]; then
|
||||
echo "Error: this script targets macOS. For Linux, follow Dockerfile.base/2/3 directly." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$(id -u)" -eq 0 ]]; then
|
||||
echo "Error: do not run as root. Homebrew refuses, and the prefix is your \$HOME." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v brew &>/dev/null; then
|
||||
echo "Error: Homebrew not found. Install from https://brew.sh and retry." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v git &>/dev/null; then
|
||||
echo "Error: git not found in PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Configuration"
|
||||
echo "FFmpeg tag : $FFMPEG_TAG"
|
||||
echo "Prefix : $PREFIX"
|
||||
echo "Source dir : $SRC_DIR"
|
||||
echo "Parallel : $JOBS jobs"
|
||||
|
||||
# --- Step 1: Install Homebrew deps -------------------------------------------
|
||||
|
||||
log "Step 1: Installing Homebrew dependencies"
|
||||
INSTALLED="$(brew list --formula 2>/dev/null || true)"
|
||||
TO_INSTALL=()
|
||||
for pkg in "${REQUIRED_BREW_PKGS[@]}"; do
|
||||
if echo "$INSTALLED" | grep -qx "$pkg"; then
|
||||
echo " ok $pkg"
|
||||
else
|
||||
echo " miss $pkg"
|
||||
TO_INSTALL+=("$pkg")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#TO_INSTALL[@]} -gt 0 ]]; then
|
||||
echo ""
|
||||
echo "Installing missing packages: ${TO_INSTALL[*]}"
|
||||
brew install "${TO_INSTALL[@]}"
|
||||
else
|
||||
echo ""
|
||||
echo "All required Homebrew packages already installed."
|
||||
fi
|
||||
|
||||
# --- Step 2: Clone or refresh ffmpeg source ----------------------------------
|
||||
|
||||
log "Step 2: Fetching ffmpeg source at $FFMPEG_TAG"
|
||||
mkdir -p "$(dirname "$SRC_DIR")"
|
||||
if [[ ! -d "$SRC_DIR/.git" ]]; then
|
||||
# Shallow clone of just the tag we want — full history is ~600 MB and
|
||||
# takes minutes to index; this drops to ~80 MB and seconds.
|
||||
git clone --depth 1 --branch "$FFMPEG_TAG" \
|
||||
https://github.com/FFmpeg/FFmpeg.git "$SRC_DIR"
|
||||
else
|
||||
cd "$SRC_DIR"
|
||||
git fetch --depth 1 --tags --quiet origin "$FFMPEG_TAG"
|
||||
fi
|
||||
cd "$SRC_DIR"
|
||||
git checkout --quiet "$FFMPEG_TAG"
|
||||
echo "Checked out: $(git describe --tags --always)"
|
||||
|
||||
# --- Step 3: Configure --------------------------------------------------------
|
||||
|
||||
log "Step 3: Configuring ffmpeg"
|
||||
|
||||
# openssl@3 is keg-only in Homebrew, so its .pc files are not on the default
|
||||
# PKG_CONFIG_PATH. Other deps (lame in particular) ship no .pc at all, so
|
||||
# also pass --extra-cflags / --extra-ldflags pointing at the Homebrew prefix
|
||||
# (works for both Apple Silicon /opt/homebrew and Intel /usr/local).
|
||||
BREW_PREFIX="$(brew --prefix)"
|
||||
OPENSSL_PREFIX="$(brew --prefix openssl@3)"
|
||||
export PKG_CONFIG_PATH="$OPENSSL_PREFIX/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
|
||||
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH"
|
||||
|
||||
# --enable-nonfree : required by --enable-libfdk-aac
|
||||
# --enable-gpl : required by --enable-libx264 / --enable-libx265 / --enable-libass
|
||||
# --enable-version3 : allow (L)GPLv3 components alongside GPL/nonfree
|
||||
# --enable-openssl : DTLS backend; the WHIP muxer needs this for the
|
||||
# DTLS-SRTP handshake. ffmpeg's WHIP muxer uses ffmpeg's
|
||||
# *internal* SRTP (libavformat/srtp.c), not external
|
||||
# libsrtp — so no --enable-libsrtp flag exists/is needed.
|
||||
# --enable-libsrt : SRT protocol (publish/play)
|
||||
./configure \
|
||||
--prefix="$PREFIX" \
|
||||
--extra-cflags="-I$BREW_PREFIX/include" \
|
||||
--extra-ldflags="-L$BREW_PREFIX/lib" \
|
||||
--enable-gpl \
|
||||
--enable-nonfree \
|
||||
--enable-version3 \
|
||||
--enable-openssl \
|
||||
--enable-libsrt \
|
||||
--enable-libx264 \
|
||||
--enable-libx265 \
|
||||
--enable-libvpx \
|
||||
--enable-libfdk-aac \
|
||||
--enable-libmp3lame \
|
||||
--enable-libopus \
|
||||
--enable-libass \
|
||||
--enable-libfreetype \
|
||||
--enable-libfontconfig \
|
||||
--enable-libharfbuzz \
|
||||
--enable-libfribidi \
|
||||
--enable-videotoolbox \
|
||||
--enable-audiotoolbox \
|
||||
--disable-debug
|
||||
|
||||
# --- Step 4: Build and install -----------------------------------------------
|
||||
|
||||
log "Step 4: Building ffmpeg ($JOBS jobs)"
|
||||
make -j"$JOBS"
|
||||
|
||||
log "Step 5: Installing to $PREFIX"
|
||||
make install
|
||||
|
||||
# --- Step 5: Verify -----------------------------------------------------------
|
||||
|
||||
log "Step 6: Verifying installed binary"
|
||||
FFMPEG_BIN="$PREFIX/bin/ffmpeg"
|
||||
if [[ ! -x "$FFMPEG_BIN" ]]; then
|
||||
echo "Error: $FFMPEG_BIN missing after install." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
"$FFMPEG_BIN" -version | head -2
|
||||
echo ""
|
||||
|
||||
if "$FFMPEG_BIN" -hide_banner -muxers 2>/dev/null | grep -qw whip; then
|
||||
echo "PASS: WHIP muxer is available."
|
||||
else
|
||||
echo "FAIL: WHIP muxer is NOT in the installed ffmpeg." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "$FFMPEG_BIN" -hide_banner -protocols 2>/dev/null | grep -qw srt; then
|
||||
echo "PASS: SRT protocol is available."
|
||||
else
|
||||
echo "FAIL: SRT protocol is NOT in the installed ffmpeg." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "$FFMPEG_BIN" -hide_banner -codecs 2>/dev/null | grep -E "libx264|libx265" | grep -q libx264; then
|
||||
echo "PASS: libx264 encoder is available."
|
||||
else
|
||||
echo "FAIL: libx264 encoder missing." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if "$FFMPEG_BIN" -hide_banner -codecs 2>/dev/null | grep -q libx265; then
|
||||
echo "PASS: libx265 encoder is available."
|
||||
else
|
||||
echo "FAIL: libx265 encoder missing." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
log "Done"
|
||||
echo "Binary: $FFMPEG_BIN"
|
||||
echo "Version: $("$FFMPEG_BIN" -version | head -1)"
|
||||
echo ""
|
||||
|
||||
# Warn if PATH won't pick up the new binary.
|
||||
if ! echo ":$PATH:" | grep -q ":$PREFIX/bin:"; then
|
||||
echo "NOTE: $PREFIX/bin is not on your PATH."
|
||||
echo " Add this to ~/.zshrc (or your shell rc):"
|
||||
echo " export PATH=\"\$HOME/.local/bin:\$PATH\""
|
||||
echo " Then 'which ffmpeg' should resolve to $FFMPEG_BIN."
|
||||
else
|
||||
RESOLVED="$(command -v ffmpeg || true)"
|
||||
if [[ "$RESOLVED" == "$FFMPEG_BIN" ]]; then
|
||||
echo "PATH check: 'ffmpeg' resolves to $RESOLVED ✓"
|
||||
else
|
||||
echo "NOTE: $PREFIX/bin is on PATH but 'ffmpeg' currently resolves to:"
|
||||
echo " $RESOLVED"
|
||||
echo " Reorder PATH so $PREFIX/bin comes before $(dirname "$RESOLVED")."
|
||||
fi
|
||||
fi
|
||||
Loading…
Reference in New Issue
Block a user