mirror of
git://f0xx.org/ac/ac-ms-media-transcode
synced 2026-07-29 03:57:41 +03:00
Encode-once/fanout scripts, HLS output, and single overloadable env source. Commits assets/pirate_drift.png as default watermark for cluster runs. Co-authored-by: Cursor <cursoragent@cursor.com>
119 lines
3.7 KiB
Bash
119 lines
3.7 KiB
Bash
#!/usr/bin/env bash
|
|
# Resolve pipeline input from CLI arg, sources.list index, or env SOURCE_URL.
|
|
set -euo pipefail
|
|
|
|
# shellcheck disable=SC1091
|
|
source "$(dirname "${BASH_SOURCE[0]}")/common.sh"
|
|
|
|
SOURCE_URL=""
|
|
SOURCE_FMT=""
|
|
SOURCE_VIDEO_STREAM="v:0"
|
|
SOURCE_AUDIO_STREAM="a:0"
|
|
AUDIO_INPUT_ARGS=()
|
|
USE_YTDLP=0
|
|
|
|
is_page_url() {
|
|
local url="$1"
|
|
[[ "$url" =~ ^https?:// ]] || return 1
|
|
[[ "$url" =~ \.(m3u8|mpd|mp4|mkv|mov|ts|flv)(\?|$) ]] && return 1
|
|
[[ -f "$url" ]] && return 1
|
|
return 0
|
|
}
|
|
|
|
resolve_source() {
|
|
local arg="${1:-}"
|
|
SOURCE_URL="${SOURCE_URL:-}"
|
|
SOURCE_FMT=""
|
|
|
|
if [[ -n "${SOURCE_URL}" ]]; then
|
|
:
|
|
elif [[ -n "${arg}" && -f "${arg}" && "${arg}" != *".list" ]]; then
|
|
SOURCE_URL="${arg}"
|
|
elif [[ -n "${arg}" && "${arg}" =~ ^https?:// ]]; then
|
|
SOURCE_URL="${arg}"
|
|
elif [[ -n "${arg}" && "${arg}" =~ ^[0-9]+$ ]]; then
|
|
if [[ ! -f "${SOURCES_LIST}" ]]; then
|
|
die "sources list missing: ${SOURCES_LIST} (copy sources.example.list)"
|
|
fi
|
|
local line
|
|
line="$(sed -n "${arg}p" "${SOURCES_LIST}" | sed 's/#.*//' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
|
[[ -n "${line}" ]] || die "no source on line ${arg} of ${SOURCES_LIST}"
|
|
SOURCE_URL="$(awk '{print $1}' <<<"${line}")"
|
|
SOURCE_FMT="$(awk '{print $2}' <<<"${line}")"
|
|
elif [[ -f "${SOURCES_LIST}" ]]; then
|
|
local line
|
|
line="$(grep -v '^[[:space:]]*#' "${SOURCES_LIST}" | grep -v '^[[:space:]]*$' | head -1)"
|
|
SOURCE_URL="$(awk '{print $1}' <<<"${line}")"
|
|
SOURCE_FMT="$(awk '{print $2}' <<<"${line}")"
|
|
else
|
|
die "usage: pass URL, file path, or 1-based index into ${SOURCES_LIST}"
|
|
fi
|
|
|
|
[[ -n "${SOURCE_URL}" ]] || die "empty source URL"
|
|
|
|
if [[ -n "${AUDIO_SOURCE:-}" ]]; then
|
|
read_rate_flag
|
|
AUDIO_INPUT_ARGS=("${RE_FLAG[@]}" -thread_queue_size "${THREAD_QUEUE_SIZE}" -i "${AUDIO_SOURCE}")
|
|
SOURCE_AUDIO_STREAM="a:0"
|
|
fi
|
|
|
|
if [[ "${YTDLP_ENABLED}" == "1" ]] && is_page_url "${SOURCE_URL}"; then
|
|
USE_YTDLP=1
|
|
fi
|
|
|
|
echo "${SOURCE_URL}" > "${ROOT}/.current_source"
|
|
log "source: ${SOURCE_URL} (ytdlp=${USE_YTDLP})"
|
|
}
|
|
|
|
ytdlp_auth_args() {
|
|
local auth="${ROOT}/config/yt-dlp.auth.env"
|
|
if [[ -f "${auth}" ]]; then
|
|
# shellcheck disable=SC1090
|
|
source "${auth}"
|
|
fi
|
|
local args=()
|
|
[[ -n "${YTDLP_USERNAME:-}" ]] && args+=(--username "${YTDLP_USERNAME}")
|
|
[[ -n "${YTDLP_PASSWORD:-}" ]] && args+=(--password "${YTDLP_PASSWORD}")
|
|
[[ -n "${YTDLP_NETRC:-}" ]] && args+=(--netrc)
|
|
[[ -n "${YTDLP_EXTRA_ARGS:-}" ]] && args+=(${YTDLP_EXTRA_ARGS})
|
|
printf '%s\n' "${args[@]}"
|
|
}
|
|
|
|
build_ytdlp_pipeline() {
|
|
local fmt_args=()
|
|
[[ -n "${SOURCE_FMT}" ]] && fmt_args=(-f "${SOURCE_FMT}")
|
|
mapfile -t auth < <(ytdlp_auth_args)
|
|
|
|
printf '%s\0' "${YTDLP_BIN}" \
|
|
-o - --no-part --no-live-from-start --no-write-subs --no-embed-subs \
|
|
--remux-video mkv --merge-output-format mkv --no-audio-multistreams \
|
|
--geo-bypass --ignore-errors --hls-use-mpegts \
|
|
"${auth[@]}" \
|
|
"${fmt_args[@]}" \
|
|
"${SOURCE_URL}"
|
|
}
|
|
|
|
# Returns ffmpeg input argv: either direct -i URL or pipe from yt-dlp.
|
|
build_primary_input() {
|
|
read_rate_flag
|
|
if [[ "${USE_YTDLP}" == "1" ]]; then
|
|
require_cmd "${YTDLP_BIN}"
|
|
printf '%s\0' pipe
|
|
printf '%s\0' -thread_queue_size "${THREAD_QUEUE_SIZE}" -i pipe:0
|
|
return
|
|
fi
|
|
|
|
local url="${SOURCE_URL}"
|
|
if [[ "${url}" == *.jpg || "${url}" == *.jpeg || "${url}" == *.png ]]; then
|
|
printf '%s\0' direct
|
|
printf '%s\0' "${RE_FLAG[@]}" -thread_queue_size "${THREAD_QUEUE_SIZE}" \
|
|
-loop 1 -i "${url}" -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=48000
|
|
return
|
|
fi
|
|
|
|
printf '%s\0' direct
|
|
printf '%s\0' "${RE_FLAG[@]}" -thread_queue_size "${THREAD_QUEUE_SIZE}" \
|
|
-reconnect_on_network_error 1 -reconnect_streamed 1 -reconnect_delay_max 5 \
|
|
-i "${url}"
|
|
}
|