| 
									
										
										
										
											2022-11-26 18:41:41 -05:00
										 |  |  | #!/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 )" | 
					
						
							| 
									
										
										
										
											2022-11-26 18:41:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  | : ${VIDEO_BITRATE:="1M"} # Only for encoding modes targeting bitrate | 
					
						
							|  |  |  | : ${AUDIO_BITRATE:="192k"} | 
					
						
							| 
									
										
										
										
											2022-11-26 18:41:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  | ############## Setup ######################### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function die { | 
					
						
							|  |  |  |     local status_code="$1" | 
					
						
							|  |  |  |     shift | 
					
						
							|  |  |  |     (>&2 echo "${@}") | 
					
						
							|  |  |  |     exit "$status_code" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function log { | 
					
						
							|  |  |  |     (>&2 echo "${@}") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ############## Program ######################### | 
					
						
							| 
									
										
										
										
											2022-11-26 18:41:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-06 14:43:37 -04:00
										 |  |  | function main { | 
					
						
							|  |  |  |     local cmd | 
					
						
							|  |  |  |     cmd=$1 | 
					
						
							|  |  |  |     shift | 
					
						
							|  |  |  |     if [ "$cmd" = "copy" ]; then | 
					
						
							|  |  |  |         copy "${@}" | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     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" | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  | 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
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     # Verify parameters | 
					
						
							| 
									
										
										
										
											2024-10-10 18:12:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if [ "$acceleration_type" == "software" ]; then | 
					
						
							|  |  |  |         true | 
					
						
							|  |  |  |     elif [ "$acceleration_type" == "hardware" ]; then | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |         true | 
					
						
							| 
									
										
										
										
											2024-10-10 18:12:39 -04:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |         die 1 "Unknown acceleration type: $acceleration_type" | 
					
						
							| 
									
										
										
										
											2024-10-10 18:12:39 -04:00
										 |  |  |     fi | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     if [ "$codec" == "h264" ]; then | 
					
						
							|  |  |  |         true | 
					
						
							|  |  |  |     elif [ "$codec" == "av1" ]; then | 
					
						
							|  |  |  |         true | 
					
						
							| 
									
										
										
										
											2024-10-10 18:12:39 -04:00
										 |  |  |     else | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     # Build command | 
					
						
							| 
									
										
										
										
											2024-07-18 23:29:07 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     args+=(-i "$file_to_cast") | 
					
						
							| 
									
										
										
										
											2024-07-06 14:43:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05: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. | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     </dev/null exec ffmpeg "${args[@]}" | 
					
						
							| 
									
										
										
										
											2024-07-06 14:43:37 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05:00
										 |  |  |     args+=(-re -stream_loop -1) | 
					
						
							| 
									
										
										
										
											2024-07-18 23:29:07 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 21:29:42 -05: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 "${@}" |