aboutsummaryrefslogtreecommitdiffstats
path: root/ffmpeg/resize-and-transcode
blob: 2b7b962b22039647a5177a1f74bd764dcc15a5e6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/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 '\033['"${colour}m${format}"'\033[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

ttysetting="$(stty -g)"
ffmpeg -i "$input" $scale $codec -c:a copy -- "$output"
ret=$?
stty -- "$ttysetting"

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