Live video on the AT Protocol
1#!/bin/bash
2
3set -euo pipefail
4
5ONE="$(realpath "$1")"
6TWO="$(realpath "$2")"
7BASE_ONE="$(basename "$ONE")"
8BASE_TWO="$(basename "$TWO")"
9
10if [[ -d "$ONE" && -d "$TWO" ]]; then
11 FILES_ONE=$(find "$ONE" -maxdepth 1 -mindepth 1 -type f -name '*.mp4' | xargs -L 1 basename | sort)
12 FILES_TWO=$(find "$TWO" -maxdepth 1 -mindepth 1 -type f -name '*.mp4' | xargs -L 1 basename | sort)
13
14 NUM_FILES_ONE=$(echo "$FILES_ONE" | wc -l)
15 NUM_FILES_TWO=$(echo "$FILES_TWO" | wc -l)
16
17 if [[ "$NUM_FILES_ONE" -ne "$NUM_FILES_TWO" ]]; then
18 echo "Directory contents differ: different number of files"
19 comm -3 <(echo "$FILES_ONE") <(echo "$FILES_TWO")
20 exit 1
21 fi
22
23 # Compare files by their order in the sorted lists, regardless of filenames
24 paste <(echo "$FILES_ONE") <(echo "$FILES_TWO") | while read -r file_one file_two; do
25 # skip if either file entry is empty (may only occur if line counts mismatched, but that's handled above)
26 [ -n "$file_one" ] && [ -n "$file_two" ] || continue
27 echo "Comparing $file_one <=> $file_two"
28 set +e
29 "$0" "$ONE/$file_one" "$TWO/$file_two"
30 set -e
31 done
32 exit 0
33fi
34
35
36cd "$(mktemp -d)"
37HASH_ONE=$(openssl sha256 "$ONE" | awk '{print $2}')
38HASH_TWO=$(openssl sha256 "$TWO" | awk '{print $2}')
39if [ "$HASH_ONE" = "$HASH_TWO" ]; then
40 echo "Identical: $BASE_ONE $BASE_TWO $(pwd)"
41 exit 0
42fi
43pwd
44echo "Hash for $ONE: $HASH_ONE"
45echo "Hash for $TWO: $HASH_TWO"
46
47xxd "$ONE" > "1.xxd"
48xxd "$TWO" > "2.xxd"
49(diff --color=always "1.xxd" "2.xxd" || true) | head -n 5
50
51ffmpeg -y -loglevel fatal -i "$ONE" -c copy -f framemd5 "1.md5"
52ffmpeg -y -loglevel fatal -i "$TWO" -c copy -f framemd5 "2.md5"
53(diff --color=always "1.md5" "2.md5" || true) | head -n 5
54
55ffprobe -loglevel fatal -show_frames "$ONE" > "1.frames"
56ffprobe -loglevel fatal -show_frames "$TWO" > "2.frames"
57(diff --color=always "1.frames" "2.frames" || true) | head -n 5
58
59set +e
60echo -e "\033[0m"
61video_frames_one="$(cat 1.frames | grep media_type=video | wc -l | xargs)"
62video_frames_two="$(cat 2.frames | grep media_type=video | wc -l | xargs)"
63if [[ "$video_frames_one" -ne "$video_frames_two" ]]; then
64 echo "Video frame count mismatch: $video_frames_one -> $video_frames_two"
65fi
66set -e
67
68audio_frames_one="$(cat 1.frames | grep media_type=audio | wc -l | xargs)"
69audio_frames_two="$(cat 2.frames | grep media_type=audio | wc -l | xargs)"
70if [[ "$audio_frames_one" -ne "$audio_frames_two" ]]; then
71 echo "Audio frame count mismatch: $audio_frames_one -> $audio_frames_two"
72fi
73
74# ffmpeg -y -loglevel fatal -i "$ONE" -frames:v 1 -c copy -an 1frame.h264
75# ffmpeg -y -loglevel fatal -i "$TWO" -frames:v 1 -c copy -an 2frame.h264
76
77bash -c "ffmpeg -y -bsf:v trace_headers -i \"$ONE\" -c copy -f null /dev/null 2>&1" | sed 's/\[trace_headers @ 0x[0-9a-f]*\]//' > 1.trace_headers
78bash -c "ffmpeg -y -bsf:v trace_headers -i \"$TWO\" -c copy -f null /dev/null 2>&1" | sed 's/\[trace_headers @ 0x[0-9a-f]*\]//' > 2.trace_headers
79(diff --color=always "1.trace_headers" "2.trace_headers" || true) | head -n 5
80
81go install github.com/Eyevinn/mp4ff/cmd/mp4ff-info@latest || true
82mp4ff-info "$ONE" > 1.mp4ff-info
83mp4ff-info "$TWO" > 2.mp4ff-info
84(diff --color=always "1.mp4ff-info" "2.mp4ff-info" || true) | head -n 5
85
86# ffmpeg -y -loglevel fatal -i "$ONE" -c copy 1tweaked.mp4
87# ffmpeg -y -loglevel fatal -i "$TWO" -c copy 2tweaked.mp4
88
89# ffmpeg -y -bsf:v trace_headers -i 1tweaked.mp4 -c copy -f null /dev/null 2>&1 | sed 's/.*\]//' > 1.trace_headers
90# ffmpeg -y -bsf:v trace_headers -i 2tweaked.mp4 -c copy -f null /dev/null 2>&1 | sed 's/.*\]//' > 2.trace_headers
91
92# diff --color=always "1.trace_headers" "2.trace_headers" || true
93
94# ffmpeg -y -loglevel fatal -bsf:v h264_redundant_pps -i "$ONE" -c copy 1tweaked.mp4
95# ffmpeg -y -loglevel fatal -bsf:v h264_redundant_pps -i "$TWO" -c copy 2tweaked.mp4
96
97# ffmpeg -y -loglevel fatal -i 1tweaked.mp4 -c copy -f framemd5 "1tweaked.mp4.md5"
98# ffmpeg -y -loglevel fatal -i 2tweaked.mp4 -c copy -f framemd5 "2tweaked.mp4.md5"
99# (diff --color=always "1tweaked.mp4.md5" "2tweaked.mp4.md5" || true)
100
101# (diff --color=always "1.trace_headers" "2.trace_headers" || true)
102
103# ffmpeg -y -loglevel fatal -i "$ONE" -c:v copy -bsf:v h264_mp4toannexb -an 1.ts
104# ffmpeg -y -loglevel fatal -i "$TWO" -c:v copy -bsf:v h264_mp4toannexb -an 2.ts
105# ffmpeg -y -loglevel fatal -i 1.ts -c copy -f framemd5 "1.ts.md5"
106# ffmpeg -y -loglevel fatal -i 2.ts -c copy -f framemd5 "2.ts.md5"
107# (diff --color=always "1.ts.md5" "2.ts.md5" || true)
108
109echo -e "\033[0m"
110echo "Useful commands:"
111echo "Compare ffprobe -show_frames data:"
112echo " meld $(realpath 1.frames) $(realpath 2.frames)"
113echo "Compare frame headers:"
114echo " meld $(realpath 1.trace_headers) $(realpath 2.trace_headers)"
115echo "Compare hex hashes:"
116echo " meld $(realpath 1.xxd) $(realpath 2.xxd)"
117echo "Compare framemd5 hashes:"
118echo " meld $(realpath 1.md5) $(realpath 2.md5)"
119echo "Compare mp4ff-info data:"
120echo " meld $(realpath 1.mp4ff-info) $(realpath 2.mp4ff-info)"
121exit 1