在尝试使用带有 runOnInit 指令的 FFmpeg 启动回退流时,我的 MediaMTX 设置遇到了障碍。当 runOnInit 触发命令时,环境变量 $RTSP_PORT 和 $MTX_PATH 似乎没有初始化。
我的目标是让 MediaMTX 管理 RTSP 流并通过 FFmpeg 建立后备流,该流在 MediaMTX 启动时自动启动。目的是在任何主要流遇到问题时无缝切换到后备流。
预期行为:
这是我的 YAML 配置的简化版本:
fallbackpath:
runOnInit: ffmpeg -re -stream_loop -1 -i "/path/to/fallback/video.mp4" -c:v copy -an -f rtsp "rtsp://127.0.0.1:$RTSP_PORT/$MTX_PATH"
runOnInitRestart: yes
paths:
# Primary streams
stream1:
source: rtsp://example.com/stream1
fallback: fallbackpath
stream2:
source: rtsp://example.com/stream2
fallback: fallbackpath
# More streams...
但是触发runOnInit时似乎$RTSP_PORT和$MTX_PATH不可用,导致错误。
我尝试使用 runOnDemand 指令作为替代方案,但我不确定它是否适合我的场景。不幸的是,runOnInit 和 runOnDemand 配置都失败,导致 MediaMTX 中止。
我希望得到有关确保启动回退流时正确初始化环境变量的指导。
感谢您的协助!
可能不是最干净的选项,可能应该使用“后备:”中内置的 MediaMTX,只是不知道如何,所以使用 Bash 脚本 FFMpeg 和 FFProbe 编写了我自己的版本,我认为它是否在每个 cron 上2-5秒就可以了:
#!/bin/bash
# Function to extract specific variables from .env file
extractEnvVariable() {
local envFile="${1}"
local variableName="${2}"
local variableValue=$(grep "^${variableName}=" "$envFile" | cut -d'=' -f2- | tr -d '"' | tr -d "'")
echo "$variableValue"
}
# Absolute path to the script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Paths to the .env and .env-secrets files
ENV_FILE="$SCRIPT_DIR/../.env"
# Define paths and variables
pathsConfigPath="$SCRIPT_DIR/../config/paths_config.yml"
mediamtxConfigPath="/usr/local/etc/mediamtx.yml"
streamsDirectory="$SCRIPT_DIR/../config/customers/"
LOG_FILE="/var/log/stream_conductor.log"
# Get FFProbe path, ffmpeg path, fallback URL, and stream URI from .env
FFPROBE=$(extractEnvVariable "$ENV_FILE" "FFMPEG_FFPROBE_PATH")
FFMPEG=$(extractEnvVariable "$ENV_FILE" "FFMPEG_FFMPEG_PATH")
FALLBACK=$(extractEnvVariable "$ENV_FILE" "MEDIAMTX_FALLBACK")
STREAM_URI=$(extractEnvVariable "$ENV_FILE" "MEDIAMTX_URL")
STREAM_URI=${STREAM_URI%/} # Trim trailing forward slash
# Trim trailing forward slash from STREAM_URI
STREAM_URI=${STREAM_URI%/}
# Clear log file
> "$LOG_FILE"
# Check if streams directory exists and is a directory
if [ -d "$streamsDirectory" ]; then
configContent=""
# Iterate through customer directories
customerDirectories=$(ls "$streamsDirectory")
for customerDirectory in $customerDirectories; do
if [ "$customerDirectory" != "." ] && [ "$customerDirectory" != ".." ]; then
customerPath="$streamsDirectory/$customerDirectory"
# Check if customer directory exists and is a directory
if [ -d "$customerPath" ]; then
streamPath="$customerPath/streams/"
# Check if streams directory exists and is a directory
if [ -d "$streamPath" ]; then
# Loop through stream files
for streamFile in "$streamPath"/*; do
if [ "$streamFile" != "$streamPath/*" ]; then
UUID=$(basename "$streamFile" | cut -c7-) # Assuming stream directory names start with "stream"
rtspUrlFile="$streamFile/rtsp_url_$UUID.txt"
if [ -f "$rtspUrlFile" ]; then
rtspUrl=$(<"$rtspUrlFile")
# Check if RTSP stream is active using FFProbe
if $FFPROBE -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 "$rtspUrl" >/dev/null 2>&1; then
# Stream is active, use original RTSP URL
configContent+=" $UUID:\n"
configContent+=" source: $rtspUrl\n"
else
# Stream is not active, fallback to tsdkfallback
configContent+=" $UUID:\n"
configContent+=" source: $STREAM_URI/tsdkfallback\n"
fi
fi
fi
done
else
echo "Streams directory not found or is not a directory: $streamPath" >> "$LOG_FILE"
fi
else
echo "Customer directory not found or is not a directory: $customerPath" >> "$LOG_FILE"
fi
fi
done
# Add indentation for tsdkfallback entry
configContent+=" tsdkfallback:\n"
else
echo "Streams directory not found or is not a directory: $streamsDirectory" >> "$LOG_FILE"
fi
# Write the updated content to paths_config.yml
echo -e "$configContent" > "$pathsConfigPath"
# Load original configuration from mediamtx.yml
mediamtxConfig=$(<"$mediamtxConfigPath")
# Combine mediamtx.yml and configContent
combinedConfig="$mediamtxConfig\npaths:\n$configContent"
# Write the combined configuration to config.yml
outputFilePath="/usr/local/etc/config.yml"
echo -e "$combinedConfig" > "$outputFilePath"
# Check if MediaMTX process is not already running
if ! pgrep -x "mediamtx" >/dev/null; then
# Start MediaMTX
/usr/local/bin/mediamtx "$outputFilePath" &
fi
# Check if ffmpeg process is not already running
if ! pgrep -x "ffmpeg" >/dev/null; then
# Execute ffmpeg command as a standalone process
"$FFMPEG" -re -stream_loop -1 -i "$FALLBACK" -c:v copy -an -f rtsp "$STREAM_URI/tsdkfallback" &
fi
然后将其输出到 config.yml 中,假设在此特定实例中没有摄像机在进行流传输,因此它已将所有流源默认为后备:
paths:
71fc528a-a65d-473e-ac9f-ff4751576cce:
source: rtsp://localhost:8554/tsdkfallback
a34dd062-087d-4a68-99d0-612bc4478910:
source: rtsp://localhost:8554/tsdkfallback
ab1ac337-e137-4ea1-a4a8-34843abeeffe:
source: rtsp://localhost:8554/tsdkfallback
add118ab-1f19-45ce-913d-59e242de3e08:
source: rtsp://localhost:8554/tsdkfallback
c5908bd6-9da6-44b2-8ffa-57af78ed01bd:
source: rtsp://localhost:8554/tsdkfallback
dda7a9cb-e348-44ce-98f7-cb224c8e4a9d:
source: rtsp://localhost:8554/tsdkfallback
tsdkfallback: