]> code.delx.au - transcoding/blob - fix-pal-speedup
avconv -> ffmpeg
[transcoding] / fix-pal-speedup
1 #!/bin/bash
2
3 # Many DVDs released in Australia are sped up from 24fps to 25fps.
4 # This script reverses the procedure, correcting the audio pitch.
5 # - The video framerate is adjusted without re-encoding.
6 # - The audio is slowed, and encoded as AAC, preserving surround sound.
7 # - Chapters and subtitles are also adjusted to match the new timing.
8
9 if [ -z "$1" ] || [ -z "$2" ]; then
10 echo "Usage: $0 infile outfile"
11 exit 1
12 fi
13
14 set -o pipefail -eux
15 OLDFPS="25"
16 NEWFPS="24"
17 SLOWFILTER=("-filter" "asetrate=46080,aresample=osr=48000:resampler=soxr")
18
19 function main {
20 local infile="$1"
21 local outfile="$2"
22
23 local tmpdir=""
24 tmpdir="$(mktemp -d "${TMPDIR:-/var/tmp}/pal-XXXXXXXX")"
25 local audiofile="${tmpdir}/audiofile.m4a"
26
27 encode_audio "$infile" "$audiofile"
28 remux_file "$infile" "$audiofile" "$outfile"
29
30 rm -rf "$tmpdir"
31 }
32
33 function encode_audio {
34 ffmpeg \
35 -i "$1" \
36 -vn \
37 "${SLOWFILTER[@]}" \
38 -c:a libfdk_aac -vbr 3 \
39 "$2"
40 }
41
42 function remux_file {
43 local infile="$1"
44 local audiofile="$2"
45 local outfile="$3"
46
47 local audiodelay=""
48 audiodelay="$(get_minimum_timestamp "$infile" "audio")"
49
50 local videodelay=""
51 videodelay="$(get_minimum_timestamp "$infile" "video")"
52
53 local videotrackid=""
54 videotrackid="$(get_track_id "$infile" "video")"
55
56 local suboptions=()
57 local subtitletrackid=""
58 while read -r subtitletrackid; do
59 suboptions+=("--sync" "${subtitletrackid}:0,${OLDFPS}/${NEWFPS}")
60 done < <(get_track_id "$infile" "subtitles")
61
62 local chapteroptions=()
63 if [ "$(get_chapter_count "$infile")" -gt 0 ]; then
64 chapteroptions=("--chapter-sync" "0,${OLDFPS}/${NEWFPS}")
65 fi
66
67 mkvmerge \
68 -o "${outfile}" \
69 --default-duration "${videotrackid}:${NEWFPS}fps" \
70 --sync "${videotrackid}:$((videodelay / 1000000))" \
71 "${chapteroptions[@]}" \
72 "${suboptions[@]}" \
73 --no-audio "$infile" \
74 --sync "0:$((audiodelay / 1000000))" \
75 "$audiofile"
76 }
77
78 function get_track_id {
79 mkvmerge -i -F json "$1" | jq -r ".tracks[] | select(.type == \"$2\") | .id"
80 }
81
82 function get_minimum_timestamp {
83 mkvmerge -i -F json "$1" | jq -r ".tracks[] | select(.type == \"$2\") | .properties.minimum_timestamp"
84 }
85
86 function get_chapter_count {
87 mkvmerge -i -F json "$1" | jq -r ".chapters | length"
88 }
89
90 main "$@"