My FFmpeg Bash Functions
remove_extension() {
sed -E 's/^(.+)\.[^.]+$/\1/'
}
get_extension() {
sed -E '/^\.?[^.]+$/d; s/^.+\.([^.]*)$/\1/'
}
ffmpeg_av1_opus() {
if [ "$#" -lt 4 ]; then
return
fi
ffmpeg -i "$4" -c:v libsvtav1 -preset "$1" -crf "$2" -c:a libopus -vbr:a 1 -b:a "$3" "${5:-"$(echo "$4" | remove_extension)_ffmpeg_av1_$1_$2_opus_$3.mkv"}"
}
ffmpeg_av1_lossless_flac() {
if [ "$#" -eq 0 ]; then
return
fi
ffmpeg -i "$1" -c:v libsvtav1 -svtav1-params lossless=1 -preset -2 -c:a flac "${2:-"$(echo "$1" | remove_extension)_ffmpeg_av1_lossless_flac.mkv"}"
}
ffmpeg_opus() {
if [ "$#" -lt 2 ]; then
return
fi
ffmpeg -i "$2" -c:a libopus -vbr:a 1 -b:a "$1" "${3:-"$(echo "$2" | remove_extension)_ffmpeg_opus_$1.opus"}"
}
ffmpeg_flac() {
if [ "$#" -eq 0 ]; then
return
fi
ffmpeg -i "$1" -c:a flac "${2:-"$(echo "$1" | remove_extension)_ffmpeg_flac.flac"}"
}
ffmpeg_segment() {
if [ "$#" -lt 2 ]; then
return
fi
ffmpeg -i "$2" -c copy -map 0 -segment_time "$1" -f segment -reset_timestamps 1 "${3:-"$(echo "$2" | remove_extension)_ffmpeg_%04d.$(echo "$2" | get_extension)"}"
}
ffmpeg_concat_auto() {
local files=()
if [ "$#" -eq 0 ]; then
for f in *; do
test -f "$f" && files+=("$f")
done
else
files=("$@")
fi
ffmpeg -f concat -safe 0 -i <(printf "file '$PWD/%s'\n" "${files[@]}") -c copy "$(echo "${files[0]}" | remove_extension | sed -E 's/_ffmpeg_[0-9]+$//').$(echo "${files[0]}" | get_extension)"
}
ffmpeg_concat() {
if [ "$#" -lt 2 ]; then
return
fi
ffmpeg -f concat -safe 0 -i <(printf "file '$PWD/%s'\n" "${@:2}") -c copy "$1"
}
echo_non_ffmpeg() {
while IFS= read -r -d '' f; do
case "${f,,}" in
*ffmpeg_*)
;;
*)
echo "$f"
;;
esac
done < <(find . -type f -print0)
}
remove_non_ffmpeg() {
while IFS= read -r -d '' f; do
case "${f,,}" in
*ffmpeg_*)
;;
*)
rm -f "$f"
;;
esac
done < <(find . -type f -print0)
}
echo_ffmpeg() {
while IFS= read -r -d '' f; do
case "${f,,}" in
*ffmpeg_*)
echo "$f"
;;
*)
;;
esac
done < <(find . -type f -print0)
}
remove_ffmpeg() {
while IFS= read -r -d '' f; do
case "${f,,}" in
*ffmpeg_*)
rm -f "$f"
;;
*)
;;
esac
done < <(find . -type f -print0)
}
mv_space_underscore() {
while IFS= read -r -d '' f; do
new="${f// /_}"
[[ -e "$new" ]] && {
echo "skipping '$f', '$new' exists"
continue
}
mv -- "$f" "$new"
done < <(find . -depth -name '* *' -print0)
}
mv_space_hyphen() {
while IFS= read -r -d '' f; do
new="${f// /-}"
[[ -e "$new" ]] && {
echo "skipping '$f', '$new' exists"
continue
}
mv -- "$f" "$new"
done < <(find . -depth -name '* *' -print0)
}
Edit: Add -vbr:a 1 to opus, thanks to exdor.
3 replies
Very nice! Will see what I can adapt
I would recommend to always use vbr for opus
There are 2 modes 1 and 2, not sure why, but 1 resulted in smaller files while taking a bit longer so I use that.
How big are these lossless encodes? I expect HUGE? flac is smaller than some weird dolby formats though.
I really like your shell magic for the concatenation, way more efficient than building a filelist.txt
Also really nice way you handle the extension
-vbr0 means CBR (constant bitrate), 1 means normal VBR (variable bitrate), 2 means constrained VBR, and 1 is the default for most build I think.-acis audio channel. 1 is mono, 2 is stereo, 6/8 are 5.1/7.1 surround, so I think I'll keep it unspecified since some movies or Dolby Atmos things use >2 channels.Thanks for your recommendation.
Regarding lossless encoding, I find flac much smaller than wav, another lossless format, while lossless AV1 is quite huge in size when converting from H264/H265.