first commit
This commit is contained in:
126
s3-ffmpeg-stream/entrypoint.sh
Normal file
126
s3-ffmpeg-stream/entrypoint.sh
Normal file
@@ -0,0 +1,126 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# --- Configuration (from environment variables with defaults) ---
|
||||
URLS="${URLS:-}"
|
||||
URLS_FILE="${URLS_FILE:-/app/urls.txt}"
|
||||
LOOP="${LOOP:-1}"
|
||||
PROTOCOL="${PROTOCOL:-udp}" # udp | rtp | rtmp | icecast
|
||||
TARGET="${TARGET:-udp://239.0.0.1:1234?ttl=16}"
|
||||
CODEC="${CODEC:-aac}"
|
||||
COPY_CODEC_WHEN_POSSIBLE="${COPY_CODEC_WHEN_POSSIBLE:-1}"
|
||||
BITRATE="${BITRATE:-160k}"
|
||||
SAMPLE_RATE="${SAMPLE_RATE:-48000}"
|
||||
FFMPEG_EXTRA_ARGS="${FFMPEG_EXTRA_ARGS:-}"
|
||||
|
||||
# --- Globals ---
|
||||
PID_FILE="/tmp/ffmpeg.pid"
|
||||
PLAYLIST_FILE="/tmp/playlist.txt"
|
||||
declare -a URL_LIST=()
|
||||
declare -a CODEC_ARGS=()
|
||||
declare -a OUTPUT_FORMAT_ARGS=()
|
||||
|
||||
# --- Functions ---
|
||||
|
||||
# Graceful cleanup on exit
|
||||
cleanup() {
|
||||
rm -f "$PID_FILE" "$PLAYLIST_FILE"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Populates URL_LIST from environment or file
|
||||
get_urls() {
|
||||
local raw_urls=()
|
||||
if [[ -n "$URLS" ]]; then
|
||||
IFS=$'\n,' read -r -d '' -a raw_urls < <(printf '%s\0' "$URLS")
|
||||
elif [[ -f "$URLS_FILE" ]]; then
|
||||
mapfile -t raw_urls < "$URLS_FILE"
|
||||
fi
|
||||
|
||||
# Trim whitespace and remove empty entries
|
||||
for u in "${raw_urls[@]:-}"; do
|
||||
u="$(echo "$u" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')"
|
||||
[[ -n "$u" ]] && URL_LIST+=("$u")
|
||||
done
|
||||
}
|
||||
|
||||
# Creates the playlist file for ffmpeg's concat demuxer
|
||||
build_playlist() {
|
||||
: > "$PLAYLIST_FILE"
|
||||
for u in "${URL_LIST[@]}"; do
|
||||
printf "file '%s'\n" "$u" >> "$PLAYLIST_FILE"
|
||||
done
|
||||
}
|
||||
|
||||
# Sets OUTPUT_FORMAT_ARGS based on the streaming protocol
|
||||
get_output_format_args() {
|
||||
case "$PROTOCOL" in
|
||||
udp) OUTPUT_FORMAT_ARGS=(-f mpegts) ;;
|
||||
rtp) OUTPUT_FORMAT_ARGS=(-f rtp) ;;
|
||||
rtmp) OUTPUT_FORMAT_ARGS=(-f flv) ;;
|
||||
icecast) OUTPUT_FORMAT_ARGS=(-content_type audio/mpeg -f mp3) ;;
|
||||
*) echo "Unsupported PROTOCOL: $PROTOCOL" >&2; exit 2 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Sets CODEC_ARGS for copying or re-encoding
|
||||
get_codec_args() {
|
||||
if [[ "$COPY_CODEC_WHEN_POSSIBLE" == "1" && "$PROTOCOL" != "icecast" ]]; then
|
||||
CODEC_ARGS=(-c:a copy)
|
||||
elif [[ "$PROTOCOL" == "icecast" ]]; then
|
||||
# Icecast typically requires MP3
|
||||
CODEC_ARGS=(-c:a libmp3lame -b:a "$BITRATE" -ar "$SAMPLE_RATE" -ac 2)
|
||||
else
|
||||
# Default re-encode
|
||||
CODEC_ARGS=(-c:a "$CODEC" -b:a "$BITRATE" -ar "$SAMPLE_RATE" -ac 2)
|
||||
fi
|
||||
}
|
||||
|
||||
# Runs a single ffmpeg instance
|
||||
run_ffmpeg() {
|
||||
local proto_whitelist="file,crypto,data,subfile,http,https,tcp,tls,pipe"
|
||||
|
||||
# Run in background to allow this script to wait and manage it
|
||||
ffmpeg -hide_banner -nostats -v info \
|
||||
-protocol_whitelist "$proto_whitelist" \
|
||||
-re -stream_loop -1 -f concat -safe 0 -i "$PLAYLIST_FILE" \
|
||||
-vn "${CODEC_ARGS[@]}" \
|
||||
"${OUTPUT_FORMAT_ARGS[@]}" \
|
||||
$FFMPEG_EXTRA_ARGS \
|
||||
"$TARGET" &
|
||||
|
||||
echo $! > "$PID_FILE"
|
||||
wait $!
|
||||
}
|
||||
|
||||
# --- Main Execution ---
|
||||
main() {
|
||||
get_urls
|
||||
if [[ ${#URL_LIST[@]} -eq 0 ]]; then
|
||||
echo "No URLs provided. Set URLS env or mount a file at $URLS_FILE." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
get_output_format_args
|
||||
get_codec_args
|
||||
build_playlist
|
||||
|
||||
echo "Starting stream from ${#URL_LIST[@]} URL(s) → $PROTOCOL → $TARGET"
|
||||
|
||||
if [[ "$LOOP" == "1" ]]; then
|
||||
while true; do
|
||||
set +e # Prevent exit on non-zero ffmpeg exit code
|
||||
run_ffmpeg
|
||||
local exit_code=$?
|
||||
set -e
|
||||
echo "FFmpeg exited with code $exit_code; restarting in 2s..."
|
||||
sleep 2
|
||||
# Rebuild playlist in case URLs have changed/expired
|
||||
build_playlist
|
||||
done
|
||||
else
|
||||
run_ffmpeg
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user