-
Notifications
You must be signed in to change notification settings - Fork 1
/
fps_conform.sh
199 lines (163 loc) · 6.6 KB
/
fps_conform.sh
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#!/bin/bash
# Current directory script is being executed from
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Folder parameter
FOLDER="$1"
# FPS parameter
FPS="$2"
USAGE="USAGE: bash fps_conform.sh [folder] [framerate]\n [folder] = location of video files to be converted\n [framerate] = framerate to conform to (23.976, 24, 25)"
if [[ $# == 0 ]]; then
echo -e "$USAGE"
exit 1
fi
# Checking for valid first parameter
if [[ ! -d "$FOLDER" ]]; then
echo "[ERROR] Please provide a valid folder!"
echo -e "$USAGE"
exit 1
fi
# Checking for valid second parameter
if [[ "$FPS" != "23.976" && "$FPS" != "24" && "$FPS" != "25" ]]; then
echo -e "[ERROR] Please provide the framerate to conform to!\n Valid options: 23.976, 24, 25"
echo -e "$USAGE"
exit 1
fi
# Setting output directory based on FPS
OUTPUT_VID="$DIR/temp/vid_$FPS"
OUTPUT_AUD="$DIR/temp/aud_$FPS"
OUTPUT_SUB="$DIR/temp/sub_$FPS"
# Making output directories
mkdir -p "$OUTPUT_VID"
mkdir -p "$OUTPUT_AUD"
mkdir -p "$OUTPUT_SUB"
# Folder for finished conversion
CONVERTED="$DIR/converted"
mkdir -p "$CONVERTED"
MSG_ERROR=" ➥ [ERROR ]"
MSG_NOTICE=" ➥ [NOTICE]"
# Convert video to desired FPS using mkvmerge
function CONVERT_VID () {
echo "$MSG_NOTICE Starting video conversion"
# Get index of video track
VID_INDEX=$(ffprobe -v error -of default=noprint_wrappers=1:nokey=1 -select_streams v:0 -show_entries stream=index "$1")
# Alternate for weird-ass files
# mkvmerge -q -o "$OUTPUT_VID/$OUTPUT_FILE" --sync "0:0,25/24" -d "$VID_INDEX" -A -S -T "$1"
mkvmerge -q -o "$OUTPUT_VID/$OUTPUT_FILE" --default-duration "$VID_INDEX:$FPS_OUT" -d "$VID_INDEX" -A -S -T "$1"
}
# Convert audio to desired length, compensating pitch
function CONVERT_AUD () {
echo "$MSG_NOTICE Starting audio conversion"
local channels
local layout
channels=$(ffprobe -show_entries stream=channels -select_streams a:0 -of compact=p=0:nk=1 -v 0 "$1")
if [[ "$channels" == "8" ]]; then
layout="7.1"
elif [[ "$channels" == "6" ]]; then
layout="5.1"
else
layout="stereo"
fi
ffmpeg -y -v error -i "$1" -c:a libopus -b:a 128k -filter:a "atempo=$TEMPO,aformat=channel_layouts=$layout" -vn "$OUTPUT_AUD/$OUTPUT_FILE"
}
# Convert subtitles to desired length
function CONVERT_SUB () {
echo "$MSG_NOTICE Starting subtitle conversion"
# Get subtitle language
SUBTITLE_LANG=$(ffprobe -v error -of default=noprint_wrappers=1:nokey=1 -select_streams s:0 -show_entries stream_tags=language "$1")
# Extract subtitle file if necessary, perform FPS change
if [[ ! -s "$SUBTITLE_EXT" ]]; then
echo "$MSG_NOTICE Using embedded subtitles"
ffmpeg -y -v error -i "$1" -map 0:s:0 "$OUTPUT_SUB/${OUTPUT_FILE}_original.srt"
perl "$DIR/srt/srtshift.pl" "${FPS_IN}-${FPS}" "${OUTPUT_SUB}/${OUTPUT_FILE}_original.srt" "${OUTPUT_SUB}/$OUTPUT_FILE" > "$DIR"/temp/perl.log 2>&1
else
echo "$MSG_NOTICE Using external subtitles"
perl "$DIR/srt/srtshift.pl" "${FPS_IN}-${FPS}" "$SUBTITLE_EXT" "${OUTPUT_SUB}/${OUTPUT_FILE}" > "$DIR"/temp/perl.log 2>&1
fi
}
function MUX () {
echo "$MSG_NOTICE Starting muxing"
if [[ "$SUBTITLE_TYPE" == "srt" || "$SUBTITLE_TYPE" == "subrip" && -n "$SUBTITLE_LANG" ]]; then
ffmpeg -y -v error -i "$OUTPUT_VID/$OUTPUT_FILE" -i "$OUTPUT_AUD/$OUTPUT_FILE" -i "$OUTPUT_SUB/$OUTPUT_FILE" -c copy -map 0:v:0 -map 1:a:0 -map 2:s:0 -metadata:s:2 language="$SUBTITLE_LANG" "$CONVERTED/$OUTPUT_FILE"
elif [[ "$SUBTITLE_TYPE" == "srt" || "$SUBTITLE_TYPE" == "subrip" ]]; then
ffmpeg -y -v error -i "$OUTPUT_VID/$OUTPUT_FILE" -i "$OUTPUT_AUD/$OUTPUT_FILE" -i "$OUTPUT_SUB/$OUTPUT_FILE" -c copy -map 0:v:0 -map 1:a:0 -map 2:s:0 "$CONVERTED/$OUTPUT_FILE"
elif [[ -s "$SUBTITLE_EXT" ]]; then
ffmpeg -y -v error -i "$OUTPUT_VID/$OUTPUT_FILE" -i "$OUTPUT_AUD/$OUTPUT_FILE" -i "$OUTPUT_SUB/$OUTPUT_FILE" -c copy -map 0:v:0 -map 1:a:0 -map 2:s:0 "$CONVERTED/$OUTPUT_FILE"
else
ffmpeg -y -v error -i "$OUTPUT_VID/$OUTPUT_FILE" -i "$OUTPUT_AUD/$OUTPUT_FILE" -c copy -map 0:v:0 -map 1:a:0 "$CONVERTED/$OUTPUT_FILE"
fi
}
# Loop to convert all files with mkv extension in current directory
for INPUT_FILE in "$FOLDER"/*.mkv; do
echo "FILE: $INPUT_FILE"
# Get basename of file
OUTPUT_FILE=$(basename "$INPUT_FILE")
# Get framerate of input file to make calculate conversion
FPS_IN=$(ffprobe -v error -of default=noprint_wrappers=1:nokey=1 -select_streams v:0 -show_entries stream=r_frame_rate "$INPUT_FILE")
# Check if there are subtitles embedded and if so what type
SUBTITLE_TYPE=$(ffprobe -v error -of default=noprint_wrappers=1:nokey=1 -select_streams s:0 -show_entries stream=codec_name "$INPUT_FILE")
# Check for external subtitles if there are none embedded
if [[ -z "$SUBTITLE_TYPE" ]]; then
SUBTITLE_EXT=$(printf '%s' "$(dirname "$INPUT_FILE")" && printf '/' && printf '%s' "$(basename "$INPUT_FILE" .mkv)" && printf .srt)
fi
# Error for same input and output FPS
ERR_NO_ACTION="$MSG_NOTICE Taking no action, FPS would be unchanged or is unsupported"
# Error for unsupported framerate
ERR_UNSUPPORTED="$MSG_ERROR Framerate not supported: $FPS_IN"
# By default take action
PASS="false"
# Determine action, tempo
if [[ "$FPS_IN" == "24000/1001" ]]; then
FPS_IN="23.976"
if [[ "$FPS" == "25" ]]; then
FPS_OUT="25p"
TEMPO="1.042709376"
echo "$MSG_NOTICE Converting from ${FPS_IN}fps to ${FPS}fps"
else
echo -e "$ERR_NO_ACTION"
PASS="true"
fi
elif [[ "$FPS_IN" == "24/1" ]]; then
FPS_IN="24"
if [[ "$FPS" == "25" ]]; then
FPS_OUT="25p"
TEMPO="1.041666667"
echo "$MSG_NOTICE Converting from ${FPS_IN}fps to ${FPS}fps"
else
echo -e "$ERR_NO_ACTION"
PASS="true"
fi
elif [[ "$FPS_IN" == "25/1" ]]; then
FPS_IN="25"
if [[ "$FPS" == "24" ]]; then
FPS_OUT="24p"
TEMPO="0.96"
echo "$MSG_NOTICE Converting from ${FPS_IN}fps to ${FPS}fps"
elif [[ "$FPS" == "23.976" ]]; then
FPS_OUT="24000/1001p"
TEMPO="0.95904"
echo "$MSG_NOTICE Converting from ${FPS_IN}fps to ${FPS}fps"
else
echo -e "$ERR_NO_ACTION"
PASS="true"
fi
else
echo "$ERR_UNSUPPORTED"
PASS="true"
fi
# Do conversion for files not set to pass
if [[ "$PASS" != "true" ]]; then
CONVERT_VID "$INPUT_FILE"
CONVERT_AUD "$INPUT_FILE"
if [[ "$SUBTITLE_TYPE" == "srt" || "$SUBTITLE_TYPE" == "subrip" || -s "$SUBTITLE_EXT" ]]; then
CONVERT_SUB "$INPUT_FILE"
else
echo "$MSG_NOTICE No SRT subtitles found"
fi
MUX "$INPUT_FILE"
# Delete intermediary files to save space
rm -f "$OUTPUT_VID/$INPUT_FILE"
rm -f "$OUTPUT_AUD/$INPUT_FILE"
fi
done
# Clean up
rm -rf "$DIR/temp"