238 lines
5.9 KiB
Plaintext
Raw Permalink Normal View History

#!/usr/bin/env bash
#
2024-07-06 14:43:37 -04:00
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
: ${VIDEO_BITRATE:="1M"} # Only for encoding modes targeting bitrate
: ${AUDIO_BITRATE:="192k"}
############## Setup #########################
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
2024-07-06 14:43:37 -04:00
function main {
local cmd
cmd=$1
shift
if [ "$cmd" = "copy" ]; then
copy "${@}"
elif [ "$cmd" = "convert" ]; then
convert "${@}"
elif [ "$cmd" = "stream" ]; then
stream "${@}"
2024-07-06 14:43:37 -04:00
elif [ "$cmd" = "webcam" ]; then
webcam "${@}"
elif [ "$cmd" = "encode_webcam" ]; then
encode_webcam "${@}"
else
(>&2 echo "Unknown command: $cmd")
exit 1
fi
}
function copy {
local file_to_cast
file_to_cast="$3"
local USERNAME PASSWORD
USERNAME="$1"
PASSWORD="$2"
2024-07-18 23:29:07 -04:00
set -x
2024-07-21 21:48:48 -04:00
</dev/null exec ffmpeg \
2024-07-06 14:43:37 -04:00
-re \
-stream_loop -1 \
-i "$file_to_cast" \
-c copy \
2024-07-18 23:29:07 -04:00
-strict experimental \
2024-07-06 14:43:37 -04:00
-f rtsp \
2024-07-17 19:46:43 -04:00
-rtsp_transport tcp \
2024-07-06 14:43:37 -04:00
"rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}
function convert {
local args=()
local acceleration_type="$1" # "software" or "hardware"
local codec="$2" # "h264" or "av1"
local file_to_cast="$3"
local file_to_save="$4"
2024-10-10 18:12:39 -04:00
# Verify parameters
2024-10-10 18:12:39 -04:00
if [ "$acceleration_type" == "software" ]; then
true
elif [ "$acceleration_type" == "hardware" ]; then
true
2024-10-10 18:12:39 -04:00
else
die 1 "Unknown acceleration type: $acceleration_type"
2024-10-10 18:12:39 -04:00
fi
if [ "$codec" == "h264" ]; then
true
elif [ "$codec" == "av1" ]; then
true
2024-10-10 18:12:39 -04:00
else
die 1 "Unknown codec: $codec"
2024-10-10 18:12:39 -04:00
fi
2024-07-06 14:43:37 -04:00
2024-10-09 21:09:11 -04:00
2024-07-18 23:29:07 -04:00
# Build command
2024-07-18 23:29:07 -04:00
if [ "$acceleration_type" == "software" ]; then
true
elif [ "$acceleration_type" == "hardware" ]; then
args+=(-vaapi_device /dev/dri/renderD128)
fi
2024-07-18 23:29:07 -04:00
args+=(-i "$file_to_cast")
2024-07-06 14:43:37 -04:00
if [ "$codec" == "h264" ]; then
if [ "$acceleration_type" == "software" ]; then
args+=(-c:v h264)
args+=(-profile:v high)
args+=(-b:v "$VIDEO_BITRATE")
elif [ "$acceleration_type" == "hardware" ]; then
args+=(-vf 'format=nv12|vaapi,hwupload')
args+=(-c:v h264_vaapi)
args+=(-profile:v high)
args+=(-b:v "$VIDEO_BITRATE")
fi
elif [ "$codec" == "av1" ]; then
if [ "$acceleration_type" == "software" ]; then
args+=(-c:v libsvtav1)
args+=(-preset 4) # [0-13] default 10, lower = higher quality / slower encode
args+=(-crf 20) # [0-63] default 35, lower = higher quality / larger file
# Parameters: https://gitlab.com/AOMediaCodec/SVT-AV1/-/blob/master/Docs/Parameters.md
# fast-decode [0-2] default 0 (off), higher = faster decode
# tune [0-2] default 1, Specifies whether to use PSNR or VQ as the tuning metric [0 = VQ, 1 = PSNR, 2 = SSIM]
# film-grain-denoise, setting to 0 uses the original frames instead of denoising the film grain
args+=(-svtav1-params "fast-decode=1:film-grain-denoise=0")
elif [ "$acceleration_type" == "hardware" ]; then
# -c:v av1_amf -quality quality
args+=(-vf 'format=nv12|vaapi,hwupload')
args+=(-c:v av1_vaapi)
args+=(-b:v "$VIDEO_BITRATE")
fi
fi
2024-07-18 23:29:07 -04:00
# -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
args+=(-bf 0)
args+=(-strict -2)
args+=(-c:a opus)
args+=(-ac 2)
args+=(-b:a "$AUDIO_BITRATE")
args+=(-ar 48000)
args+=("$file_to_save")
2024-07-18 23:29:07 -04:00
set -x
</dev/null exec ffmpeg "${args[@]}"
2024-07-06 14:43:37 -04:00
}
function stream {
local args=()
local acceleration_type="$1" # "software" or "hardware"
local codec="$2" # "h264" or "av1"
2024-07-18 23:29:07 -04:00
local USERNAME="$3"
local PASSWORD="$4"
local file_to_cast="$5"
2024-07-13 13:15:04 -04:00
2024-07-18 23:29:07 -04:00
args+=(-re -stream_loop -1)
2024-07-18 23:29:07 -04:00
args+=(-f rtsp)
args+=(-rtsp_transport tcp)
args+=("rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch")
2024-07-18 23:29:07 -04:00
}
2024-07-06 14:43:37 -04:00
function webcam {
# Uses on-webcam h264 encoding.
local USERNAME PASSWORD
USERNAME="$1"
PASSWORD="$2"
2024-07-18 23:29:07 -04:00
set -x
2024-07-21 21:48:48 -04:00
</dev/null exec ffmpeg \
2024-07-06 14:43:37 -04:00
-re \
-input_format h264 \
-video_size 1920x1080 \
-i /dev/video0 \
-c:v copy \
-an \
-f rtsp \
2024-07-17 19:46:43 -04:00
-rtsp_transport tcp \
2024-07-06 14:43:37 -04:00
"rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}
function encode_webcam {
# Uses hardware accelerated gpu-based encoding.
local USERNAME PASSWORD
USERNAME="$1"
PASSWORD="$2"
2024-07-18 23:29:07 -04:00
set -x
2024-07-21 21:48:48 -04:00
</dev/null exec ffmpeg \
2024-07-06 14:43:37 -04:00
-re \
-vaapi_device /dev/dri/renderD128 \
-i /dev/video0 \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi \
-an \
-f rtsp \
2024-07-17 19:46:43 -04:00
-rtsp_transport tcp \
2024-07-06 14:43:37 -04:00
"rtsp://$USERNAME:$PASSWORD@172.16.16.251:8554/fetch"
}
2024-09-03 19:32:42 -04:00
function speed_up_preprocess_vp8 {
local file_to_cast file_to_save
file_to_cast="$1"
file_to_save="$2"
set -x
# -bf 0 :: Disable b-frames because webrtc doesn't support h264 streams with b-frames.
# -strict -2 :: Enable support for experimental codecs like opus.
# -b:v 2M :: Target 2 megabit/s
# -crf 10 :: Target a quality level and adjust bitrate accordingly. This should be preferred, but ideally both should be used.
# Could also use -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]"
</dev/null exec ffmpeg \
-i "$file_to_cast" \
-filter:v "setpts=0.66666666*PTS" \
-filter:a "atempo=1.5" \
-c:v vp8 \
-b:v 2M \
-crf 10 \
-bf 0 \
-c:a opus \
-b:a 320k \
-ar 48000 \
-strict -2 \
"$file_to_save"
}
2024-07-06 14:43:37 -04:00
main "${@}"