posts
Copying here, as lemmy.world is defederated from quite some instances.
I own an old junky PC that can encode but it is slow and energy intense. Also a laptop that I dont wanna use.
This is a horrible time to buy hardware with soldered memory, but used Mac Minis are available.
I am looking for raw and efficient CPU power because from my experience GPU acceleration for encoding always sucks (got an Intel Arc with qsv av1 and it is very fast but less efficient and inconsistent)
I want to use ffmpeg with svt-av1 and a few filters for artificial grain generation or noise reduction. With my PC, these filters totally kill performance, from 1,5x speed to 0,1-0,05x speed easily.
Anyone here use a mac mini for software encoding? Even better, with Linux, and with svt-av1?
I wonder what might cause these slowdowns and if unified and crazy fast memory might be able to improve this.
Also, how is memory used here? For my usual ffmpeg encodes I dont need more than 16GB of memory, and that is VERY widely available (used market; shitty low spec hardware is way more frequent).
I would try and get NixOS with Asahi kernel and patches to run there, maybe also just Asahi? Never used Arch, at least it doesnt have version upgrades like Fedora that break.
Maybe run it as a headless encoding server and connect over ssh, access my files from my server and control via my laptop
I used this today to try and find a frame showing a blinking error dialog, but wasnt successful, anyways here it is!
ffmpeg -i video.mp4 -r 30 frame%d.png
- -r is the FPS
- the %d is a nice iterator, works in fish and bash apparently
Images to video
Useful for timelapses!
#!/bin/sh
fps=10
ffmpeg \
-framerate $fps \
-pattern_type glob \
-i '*.jpg' \
-c:v libsvtav1 \
-crf 20 -preset 6 \
-vf "scale=-2:1080" \
timelapse.mp4
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.
Hi all!
Only after I made an account on this instance I saw that there already is a community on lemmy.world. many instances might defederate, so this one is useful.
My motivation: I use / have used ffmpeg for
- encoding any audio to opus, variable bitrate (there are 2 modes, not sure why and mode 1 seems to be better)
- converting stereo audio to mono, duplicated to 2 channels
- cutting audio and video
- encoding any kind of video to AV1, using svt_av1 (the software encoder which sadly produces way better results than qsv_av1 on my Intel Arc)
- extracting screenshots from video
- converting multiple images into a video for timelapse recordings
- converting videos to animated images (webp)
- add metadata to videos and audios
- concatenate audiobooks in several folders to a single file including chapter metadata
- ...
I will post all my scripts here in some time and hope for an engaging community to exchange tips, parameters etc! Ffmpeg is not very easy to use but incredibly efficient!
I write this to convert my old, multiple GiB, multimedia files to formats that are smaller in size and royalty free.
remove_extension() {
sed -E 's/^(.+)\.[^.]+$/\1/'
}
get_extension() {
sed -E '/^\.?[^.]+$/d; s/^.+\.([^.]*)$/\1/'
}
ffmpeg_av1_opus() {
if [ "$#" -lt 4 ]; then
return
fi
ffmpeg -n -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 -n -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 -n -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 -n -i "$1" -c:a flac "${2:-"$(echo "$1" | remove_extension)_ffmpeg_flac.flac"}"
}
ffmpeg_segment() {
if [ "$#" -lt 2 ]; then
return
fi
ffmpeg -n -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 -n -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 -n -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)
}
jxl_lossy() {
if [ "$#" -lt 2 ]; then
return
fi
cjxl -j 0 -e 10 -d "$1" "$2" "${3:-"$(echo "$2" | remove_extension).jxl"}"
}
jxl_lossless() {
if [ "$#" -eq 0 ]; then
return
fi
cjxl -j 1 -e 10 -d 0 "$1" "${2:-"$(echo "$1" | remove_extension).jxl"}"
}
multimedia_convert() {
(
shopt -s globstar nullglob
for f in **/*; do
[[ -f $f ]] || continue
local file=${f##*/}
local dir=${f%/*}
[[ $dir == "$f" ]] && dir=.
case ${file,,} in
*.gif)
if [[ ${file##*.} != gif ]]; then
if [[ -e "${f%.*}.gif" ]]; then
printf 'Skipping: output exists: %s\n' "$f" >&2
continue
fi
mv -- "$f" "${f%.*}.gif"
fi
;;
*.flac)
if [[ ${file##*.} != flac ]]; then
if [[ -e "${f%.*}.flac" ]]; then
printf 'Skipping: output exists: %s\n' "$f" >&2
continue
fi
mv -- "$f" "${f%.*}.flac"
fi
;;
*.jpg | *.jpeg | *.png)
local jxl="${file%.*}.jxl"
if [[ -e "$dir/$jxl" ]]; then
printf 'Skipping: output exists: %s\n' "$f" >&2
continue
fi
(
cd "$dir" &&
jxl_lossy 1 "./$file" "./$jxl" &&
rm -- "$file"
)
;;
*.avif | *.bmp | *.heic | *.ico | *.jp2 | *.tif | *.webp)
local png="${file%.*}.png"
if [[ -e "$dir/$png" ]]; then
printf 'Skipping: intermediate png exists: %s\n' "$f" >&2
continue
fi
local jxl="${file%.*}.jxl"
if [[ -e "$dir/$jxl" ]]; then
printf 'Skipping: output exists: %s\n' "$f" >&2
continue
fi
(
cd "$dir" &&
magick "./$file" "./$png" && {
jxl_lossy 1 "./$png" "./$jxl" &&
rm -- "$file" ||
true
} &&
rm -f -- "$png"
)
;;
*.3gp | *.mov | *.vob | *.wmv)
(
cd "$dir" &&
ffmpeg_av1_opus 4 40 24k "./$file" &&
rm -- "$file"
)
;;
*.avi | *.mkv | *.mp4)
(
cd "$dir" &&
ffmpeg_av1_opus 4 32 72k "./$file" &&
rm -- "$file"
)
;;
*.aac | *.mp3 | *.m4a | *.ogg)
(
cd "$dir" &&
ffmpeg_opus 96k "./$file" &&
rm -- "$file"
)
;;
*.wav)
(
cd "$dir" &&
ffmpeg_flac "./$file" &&
rm -- "$file"
)
;;
*)
continue
;;
esac
done
)
}