aboutsummaryrefslogtreecommitdiffstats
path: root/ffmpeg
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2024-05-06 07:38:20 +0200
committerMattias Andrée <maandree@kth.se>2024-05-06 07:38:20 +0200
commitd7a43337a05b086533430d1a749fd177439ced66 (patch)
treec9340132c241b5cb630472790762c18fad521d9c /ffmpeg
parentmisc updates (diff)
downloaddotfiles-d7a43337a05b086533430d1a749fd177439ced66.tar.gz
dotfiles-d7a43337a05b086533430d1a749fd177439ced66.tar.bz2
dotfiles-d7a43337a05b086533430d1a749fd177439ced66.tar.xz
m
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'ffmpeg')
-rw-r--r--ffmpeg/Makefile9
-rwxr-xr-xffmpeg/resize-and-transcode126
-rwxr-xr-xffmpeg/resize-and-transcode-recursively65
3 files changed, 200 insertions, 0 deletions
diff --git a/ffmpeg/Makefile b/ffmpeg/Makefile
index c60008c..2c472b0 100644
--- a/ffmpeg/Makefile
+++ b/ffmpeg/Makefile
@@ -1,6 +1,13 @@
.POSIX:
install:
+ ../check-installed-shebang resize-and-transcode
+ ../check-installed-shebang resize-and-transcode-recursively
+ ../check-in-path rmdir test rm mv mkdir printf sed grep rev cut ffprobe ffmpeg stat
+ ../check-in-path wc && test "$$(stat -c '%s' ../README)" = "$$(wc -c < ../README | cut -d ' ' -f 1)"
+ mkdir -p -- ~/.local/bin
+ ln -sf -- ~/.dotfiles/ffmpeg/resize-and-transcode ~/.local/bin/
+ ln -sf -- ~/.dotfiles/ffmpeg/resize-and-transcode-recursively ~/.local/bin/
mkdir -p -- ~/.config/bash/aliases.d
test ! -e ~/.config/bash/aliases.d/ffmpeg || test -L ~/.config/bash/aliases.d/ffmpeg
ln -sf -- ~/.dotfiles/ffmpeg/bash-aliases ~/.config/bash/aliases.d/ffmpeg
@@ -9,3 +16,5 @@ uninstall:
+! ../check-installed ffmpeg
-unlink -- ~/.config/bash/aliases.d/ffmpeg
-rmdir -- ~/.config/bash/aliases.d
+ -unlink -- ~/.local/bin/resize-and-transcode
+ -unlink -- ~/.local/bin/resize-and-transcode-recursively
diff --git a/ffmpeg/resize-and-transcode b/ffmpeg/resize-and-transcode
new file mode 100755
index 0000000..f3fe017
--- /dev/null
+++ b/ffmpeg/resize-and-transcode
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+set -u
+
+MAX_MIN_DIM=720
+
+if test $# -lt 2 || test $# -gt 3; then
+ printf 'usage: %s input-file output-file [max-min-dim]' "$0" >&2
+ exit 3
+fi
+
+err () {
+ colour="$1"
+ format="$2"
+ shift 2
+ printf '\x1b['"${colour}m${format}"'\x1b[m\n' "$@" >&2
+}
+
+alert () { err "1;31" "$@"; }
+header () { err "1;34" "$@"; }
+subheader () { err "34" "$@"; }
+red () { err "31" "$@"; }
+green () { err "32" "$@"; }
+yellow () { err "33" "$@"; }
+magenta () { err "35" "$@"; }
+cyan () { err "36" "$@"; }
+
+input="$1"
+output="$2"
+if test $# -ge 3; then
+ MAX_MIN_DIM="$3"
+fi
+
+if test ! -f "$input" || test ! -r "$input"; then
+ red 'Input file %s does not exist or is not a readable file, skipping'
+ exit 2
+fi
+if test -e "$output" || test -L "$output"; then
+ red 'Output file %s already exists, skipping'
+ exit 2
+fi
+
+header 'Transcoding %s' "$input"
+subheader 'Outputing to %s' "$output"
+
+dimensions=$(ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=s=x:p=0 -- "$input")
+if test -z "$dimensions"; then
+ red 'An error occured, skipping'
+ exit 2
+fi
+
+oldwidth=$(printf '%s\n' "$dimensions" | cut -d 'x' -f 1)
+oldheight=$(printf '%s\n' "$dimensions" | cut -d 'x' -f 2)
+if test -z "$oldwidth" || test -z "$oldheight"; then
+ red 'An error occured, skipping'
+ exit 2
+fi
+
+scale=
+if test "$oldwidth" -lt "$oldheight"; then
+ if test "$oldwidth" -gt "${MAX_MIN_DIM}"; then
+ magenta 'The smaller dimension (width) was %i, downscaling to %i' "$oldwidth" "${MAX_MIN_DIM}"
+ newwidth="${MAX_MIN_DIM}"
+ newheight=-2
+ scale="-vf scale=$newwidth:$newheight"
+ else
+ cyan 'The smaller dimension (width) was %i, keeping as it does not exceed %i' "$oldwidth" "${MAX_MIN_DIM}"
+ fi
+else
+ if test "$oldheight" -gt "${MAX_MIN_DIM}"; then
+ magenta 'The smaller dimension (height) was %i, downscaling to %i' "$oldheight" "${MAX_MIN_DIM}"
+ newwidth=-2
+ newheight="${MAX_MIN_DIM}"
+ scale="-vf scale=$newwidth:$newheight"
+ else
+ cyan 'The smaller dimension (height) was %i, keeping as it does not exceed %i' "$oldheight" "${MAX_MIN_DIM}"
+ fi
+fi
+
+if test -z "$scale"; then
+ codec="$(ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=noprint_wrappers=1:nokey=1 -- "$input")"
+ if test -z "$codec"; then
+ red 'An error occured, skipping'
+ exit 2
+ fi
+ if test "$codec" = hevc; then
+ cyan 'Already encoded with HEVC, keeping video codec'
+ codec="-c:v copy"
+ else
+ magenta 'Encoded with %s, transcoding to HEVC' "$codec"
+ codec="-c:v libx265"
+ fi
+else
+ codec="-c:v libx265"
+fi
+
+if test -z "$scale" && test "$codec" = '-c:v copy'; then
+ yellow 'The video is already small and encoded in HEVC, skipping'
+ exit 1
+fi
+
+ffmpeg -i "$input" $scale $codec -c:a copy -- "$output"
+ret=$?
+
+if test $ret = 0; then
+ oldsize=$(stat -c '%s' -- "$input")
+ newsize=$(stat -c '%s' -- "$output")
+ if test $newsize -ge $oldsize; then
+ p=$(( 100 * (newsize - oldsize) / oldsize ))
+ yellow 'The transcoded video was larger than the original (would increase by %i%%), skipping' $p
+ if ! rm -- "$output"; then
+ alert 'Failed to remove old file: %s' "$output"
+ fi
+ exit 1
+ else
+ p=$(( 100 * (oldsize - newsize) / oldsize ))
+ green 'The transcoded video was smaller than the original (reduced by %i%%), keeping' $p
+ exit 0
+ fi
+else
+ red 'An error occured, skipping'
+ if ! rm -- "$output"; then
+ alert 'Failed to remove old file: %s' "$output"
+ fi
+ exit 2
+fi
diff --git a/ffmpeg/resize-and-transcode-recursively b/ffmpeg/resize-and-transcode-recursively
new file mode 100755
index 0000000..8a7a207
--- /dev/null
+++ b/ffmpeg/resize-and-transcode-recursively
@@ -0,0 +1,65 @@
+#!/bin/sh
+#### rmdir test rm mv mkdir printf sed grep rev cut stat(-c "%s") ffprobe ffmpeg
+
+set -u
+
+if test $# -lt 2 || test $# -gt 3 || test -z "$1" || test -z "$2"; then
+ printf "usage: %s input-dir output-dir [max-min-dim]\n" "$0" >&2
+ exit 1
+fi
+
+err () {
+ colour="$1"
+ format="$2"
+ shift 2
+ printf '\x1b['"${colour}m${format}"'\x1b[m\n' "$@" >&2
+}
+
+alert () { err "1;31" "$@"; }
+header () { err "1;34" "$@"; }
+subheader () { err "34" "$@"; }
+red () { err "31" "$@"; }
+green () { err "32" "$@"; }
+yellow () { err "33" "$@"; }
+magenta () { err "35" "$@"; }
+cyan () { err "36" "$@"; }
+
+input="$(printf '%s\n' "$1" | sed '$s/\/*$/\//')"
+output="$(printf '%s\n' "$2" | sed '$s/\/*$/\//')"
+shift 2
+
+process() {
+ d="$1"
+ shift 1
+ for f in "$d"*; do
+ if test -L "$f"; then
+ continue
+ elif test -f "$f"; then
+ if printf '%s\n' "$f" | sed -n '$p' | grep '\.tmp\.mkv$' >/dev/null; then
+ alert 'Old temporary file found: %s' "$f"
+ continue
+ fi
+ file="${f#$input}"
+ keep="$output$file"
+ tmp="$(printf '%s\n' "$f" | rev | cut -d . -f 2- | rev).tmp.mkv"
+ out="$(printf '%s\n' "$keep" | rev | cut -d . -f 2- | rev).mkv"
+ mkdir -p -- "$(dirname -- "$out")"
+ resize-and-transcode "$f" "$tmp" "$@"
+ r=$?
+ if test $r = 0; then
+ if ! mv -- "$tmp" "$out" ; then
+ alert 'Failed to move %s to %s' "$tmp" "$out"
+ elif ! rm -- "$f"; then
+ alert 'Failed to remove old file: %s' "$f"
+ fi
+ elif test $r = 1; then
+ mv -- "$f" "$keep"
+ fi
+ elif test -d "$f"; then
+ process "$f/" "$@"
+ fi
+ done
+ rmdir -- "$d" 2>/dev/null || :
+}
+
+process "$input" "$@"