234 lines
6.2 KiB
Bash
Executable File
234 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
ROOT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
BUILD_DIR="${BUILD_DIR:-$ROOT_DIR/build}"
|
|
STREAMER_BIN="${STREAMER_BIN:-$BUILD_DIR/cvmmap_streamer}"
|
|
SRS_ROOT="${SRS_ROOT:-$HOME/Code/srs}"
|
|
SRS_BIN="${SRS_BIN:-$SRS_ROOT/trunk/objs/srs}"
|
|
SRS_CONF="${SRS_CONF:-$SRS_ROOT/trunk/conf/srs.conf}"
|
|
FFPROBE_BIN="${FFPROBE_BIN:-ffprobe}"
|
|
FFMPEG_BIN="${FFMPEG_BIN:-ffmpeg}"
|
|
CURL_BIN="${CURL_BIN:-curl}"
|
|
|
|
INPUT_URI="${INPUT_URI:-}"
|
|
STREAM_NAME="${STREAM_NAME:-}"
|
|
CODEC="${CODEC:-h264}"
|
|
ENCODER_BACKEND="${ENCODER_BACKEND:-ffmpeg}"
|
|
ENCODER_DEVICE="${ENCODER_DEVICE:-nvidia}"
|
|
RTMP_TRANSPORT="${RTMP_TRANSPORT:-libavformat}"
|
|
RTMP_MODE="${RTMP_MODE:-enhanced}"
|
|
INGEST_MAX_FRAMES="${INGEST_MAX_FRAMES:-120}"
|
|
PROBE_TIMEOUT_S="${PROBE_TIMEOUT_S:-20}"
|
|
DECODE_FRAMES="${DECODE_FRAMES:-15}"
|
|
SRS_MAX_CONNECTIONS="${SRS_MAX_CONNECTIONS:-64}"
|
|
|
|
RUN_DIR="${RUN_DIR:-$BUILD_DIR/live_srs_forward_smoke_$(date +%Y%m%d_%H%M%S)}"
|
|
mkdir -p "$RUN_DIR"
|
|
|
|
SRS_LOG="$RUN_DIR/srs.log"
|
|
STREAMER_LOG="$RUN_DIR/streamer.log"
|
|
HTTP_PROBE_LOG="$RUN_DIR/ffprobe_httpflv.log"
|
|
DECODE_LOG="$RUN_DIR/ffmpeg_decode_httpflv.log"
|
|
API_LOG="$RUN_DIR/srs_api_streams.json"
|
|
SRS_TEMP_CONF="$RUN_DIR/srs.conf"
|
|
|
|
RTMP_URL="rtmp://127.0.0.1/live/${STREAM_NAME}"
|
|
HTTP_FLV_URL="http://127.0.0.1:8080/live/${STREAM_NAME}.flv"
|
|
|
|
SRS_PID=""
|
|
STREAMER_PID=""
|
|
STARTED_SRS=0
|
|
|
|
require_bin() {
|
|
local path="$1"
|
|
local label="$2"
|
|
if ! command -v "$path" >/dev/null 2>&1 && [[ ! -x "$path" ]]; then
|
|
echo "$label not found: $path" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage:
|
|
live_srs_forward_smoke.sh <input-uri> [stream-name]
|
|
|
|
Environment overrides:
|
|
INPUT_URI cvmmap source URI, if positional argument is omitted
|
|
STREAM_NAME RTMP/HTTP-FLV stream name, default derived from INPUT_URI
|
|
CODEC h264|h265
|
|
ENCODER_BACKEND ffmpeg|gstreamer_legacy
|
|
ENCODER_DEVICE auto|nvidia|software
|
|
RTMP_TRANSPORT libavformat|ffmpeg_process|legacy_custom
|
|
RTMP_MODE enhanced|domestic
|
|
INGEST_MAX_FRAMES bounded frame count for the smoke
|
|
DECODE_FRAMES frames to decode from HTTP-FLV after probe
|
|
SRS_ROOT local SRS checkout, default ~/Code/srs
|
|
EOF
|
|
}
|
|
|
|
derive_stream_name() {
|
|
local uri="$1"
|
|
local body="${uri#cvmmap://}"
|
|
local instance="${body%%@*}"
|
|
instance="${instance%%\?*}"
|
|
instance="${instance%%/*}"
|
|
if [[ -z "$instance" || "$instance" == "$uri" ]]; then
|
|
instance="stream"
|
|
fi
|
|
instance="${instance//[^a-zA-Z0-9_-]/_}"
|
|
printf '%s_live' "$instance"
|
|
}
|
|
|
|
wait_for_http() {
|
|
local url="$1"
|
|
local attempts="$2"
|
|
for _ in $(seq 1 "$attempts"); do
|
|
if "${CURL_BIN}" -fsS "$url" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep 0.25
|
|
done
|
|
return 1
|
|
}
|
|
|
|
wait_for_http_flv() {
|
|
local attempts="$1"
|
|
for _ in $(seq 1 "$attempts"); do
|
|
if "${FFPROBE_BIN}" \
|
|
-v error \
|
|
-select_streams v:0 \
|
|
-show_entries stream=index,codec_name,width,height,avg_frame_rate \
|
|
-of default=noprint_wrappers=1 \
|
|
"$HTTP_FLV_URL" >"$HTTP_PROBE_LOG" 2>&1; then
|
|
return 0
|
|
fi
|
|
if [[ -n "$STREAMER_PID" ]] && ! kill -0 "$STREAMER_PID" >/dev/null 2>&1; then
|
|
return 1
|
|
fi
|
|
sleep 0.25
|
|
done
|
|
return 1
|
|
}
|
|
|
|
print_failure_context() {
|
|
echo "--- artifacts ---" >&2
|
|
echo "RUN_DIR=$RUN_DIR" >&2
|
|
echo "--- streamer log tail ---" >&2
|
|
tail -n 120 "$STREAMER_LOG" >&2 || true
|
|
echo "--- srs log tail ---" >&2
|
|
tail -n 120 "$SRS_LOG" >&2 || true
|
|
}
|
|
|
|
cleanup() {
|
|
if [[ -n "$STREAMER_PID" ]] && kill -0 "$STREAMER_PID" >/dev/null 2>&1; then
|
|
kill "$STREAMER_PID" >/dev/null 2>&1 || true
|
|
wait "$STREAMER_PID" >/dev/null 2>&1 || true
|
|
fi
|
|
if [[ "$STARTED_SRS" -eq 1 ]] && [[ -n "$SRS_PID" ]] && kill -0 "$SRS_PID" >/dev/null 2>&1; then
|
|
kill "$SRS_PID" >/dev/null 2>&1 || true
|
|
wait "$SRS_PID" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
require_bin "$STREAMER_BIN" "streamer binary"
|
|
require_bin "$SRS_BIN" "SRS binary"
|
|
require_bin "$FFPROBE_BIN" "ffprobe"
|
|
require_bin "$FFMPEG_BIN" "ffmpeg"
|
|
require_bin "$CURL_BIN" "curl"
|
|
|
|
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -n "${1:-}" ]]; then
|
|
INPUT_URI="$1"
|
|
fi
|
|
if [[ -n "${2:-}" ]]; then
|
|
STREAM_NAME="$2"
|
|
fi
|
|
|
|
if [[ -z "$INPUT_URI" ]]; then
|
|
echo "input URI is required" >&2
|
|
usage >&2
|
|
exit 1
|
|
fi
|
|
if [[ -z "$STREAM_NAME" ]]; then
|
|
STREAM_NAME="$(derive_stream_name "$INPUT_URI")"
|
|
fi
|
|
|
|
RTMP_URL="rtmp://127.0.0.1/live/${STREAM_NAME}"
|
|
HTTP_FLV_URL="http://127.0.0.1:8080/live/${STREAM_NAME}.flv"
|
|
|
|
if [[ ! -f "$SRS_CONF" ]]; then
|
|
echo "SRS config not found: $SRS_CONF" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if wait_for_http "http://127.0.0.1:1985/api/v1/versions" 4; then
|
|
echo "Reusing running SRS on 127.0.0.1:1935"
|
|
else
|
|
sed \
|
|
-e 's/^daemon[[:space:]]\+on;/daemon off;/' \
|
|
-e "s/^max_connections[[:space:]]\\+[0-9]\\+;/max_connections ${SRS_MAX_CONNECTIONS};/" \
|
|
"$SRS_CONF" >"$SRS_TEMP_CONF"
|
|
(
|
|
cd "$SRS_ROOT/trunk"
|
|
"$SRS_BIN" -c "$SRS_TEMP_CONF" >"$SRS_LOG" 2>&1 &
|
|
echo $! >"$RUN_DIR/srs.pid"
|
|
)
|
|
SRS_PID="$(cat "$RUN_DIR/srs.pid")"
|
|
STARTED_SRS=1
|
|
if ! wait_for_http "http://127.0.0.1:1985/api/v1/versions" 40; then
|
|
echo "SRS failed to become ready on 127.0.0.1:1985" >&2
|
|
print_failure_context
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
"$STREAMER_BIN" \
|
|
--run-mode pipeline \
|
|
--input-uri "$INPUT_URI" \
|
|
--codec "$CODEC" \
|
|
--encoder-backend "$ENCODER_BACKEND" \
|
|
--encoder-device "$ENCODER_DEVICE" \
|
|
--rtmp \
|
|
--rtmp-url "$RTMP_URL" \
|
|
--rtmp-transport "$RTMP_TRANSPORT" \
|
|
--rtmp-mode "$RTMP_MODE" \
|
|
--ingest-max-frames "$INGEST_MAX_FRAMES" \
|
|
>"$STREAMER_LOG" 2>&1 &
|
|
STREAMER_PID=$!
|
|
|
|
if ! wait_for_http_flv $((PROBE_TIMEOUT_S * 4)); then
|
|
echo "HTTP-FLV stream never became probeable: $HTTP_FLV_URL" >&2
|
|
print_failure_context
|
|
exit 1
|
|
fi
|
|
|
|
if ! "$FFMPEG_BIN" -v error -i "$HTTP_FLV_URL" -an -frames:v "$DECODE_FRAMES" -f null - >"$DECODE_LOG" 2>&1; then
|
|
echo "warning: HTTP-FLV decode sample failed, see $DECODE_LOG" >&2
|
|
fi
|
|
"$CURL_BIN" -fsSL "http://127.0.0.1:1985/api/v1/streams/" >"$API_LOG" 2>/dev/null || true
|
|
|
|
wait "$STREAMER_PID"
|
|
STREAMER_RC=$?
|
|
STREAMER_PID=""
|
|
|
|
echo "RUN_DIR=$RUN_DIR"
|
|
echo "STREAMER_RC=$STREAMER_RC"
|
|
echo "INPUT_URI=$INPUT_URI"
|
|
echo "RTMP_URL=$RTMP_URL"
|
|
echo "HTTP_FLV_URL=$HTTP_FLV_URL"
|
|
echo "--- http-flv ffprobe ---"
|
|
cat "$HTTP_PROBE_LOG"
|
|
echo "--- http-flv decode log ---"
|
|
cat "$DECODE_LOG"
|
|
echo "--- srs api streams ---"
|
|
cat "$API_LOG" 2>/dev/null || true
|
|
echo "--- streamer log tail ---"
|
|
tail -n 80 "$STREAMER_LOG"
|