-
Notifications
You must be signed in to change notification settings - Fork 27
/
searchfingerprint
executable file
·178 lines (160 loc) · 7.06 KB
/
searchfingerprint
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
#!/usr/bin/env bash
SCRIPTNAME=$(basename "${0}")
SCRIPTDIR=$(dirname "${0}")
MM_CONFIG_FILE="${SCRIPTDIR}/mm.conf"
. "${SCRIPTDIR}/mmfunctions" || { echo "Missing '${SCRIPTDIR}/mmfunctions'. Exiting." ; exit 1 ;};
. "${MM_CONFIG_FILE}" || { echo "Missing '${MM_CONFIG_FILE}/mmfunctions'. Exiting." ; exit 1 ;};
_usage(){
cat << EOF;
Takes an input file, calculates a video fingerprint for specified portion, and compares results to fingerprint database
Usage: "${SCRIPTNAME}" [ -h ] [ -i ] [ -o ] [ -t ] inputfile1 | inputfile2
-h Display this help
-i Set input time in seconds for fingerprint comparison
-o Set output time in seconds for fingerprint comparison
-t Text only results (disables preview window)
EOF
exit
}
OPTIND=1
while getopts "hi:o:t" OPT ; do
case "${OPT}" in
i) INTIME="${OPTARG}" ;;
o) OUTTIME="${OPTARG}" ;;
h) _usage ;;
t) MODE="text" ;;
*) echo "bad option -${OPTARG}" ; _usage ;;
esac
done
shift $(( ${OPTIND} - 1 ))
if ! [ "${1}" ] ; then
_usage
fi
while [ "${*}" != "" ] ; do
#Set up input and temp files
INPUT="${1}"
shift
#Confirm input is a video file
if [[ -z $(file -Ib "${INPUT}" | grep video) ]] ; then
echo "Input is not a video file" && continue
fi
IO=$(mktemp)
TEMPFINGERPRINT=$(mktemp)
TEMPFINGERPRINT_SORTED=$(mktemp)
RESULTS=$(mktemp)
VISUALRESULTS=$(mktemp)
DRAWTEXT=$(mktemp)
#Set up concat input for fingerprint filter
echo "file '${INPUT}'" > "${IO}"
if [ -n "${INTIME}" ] ; then
if ! [[ "${INTIME}" =~ ^-?[0-9]+$ ]] ; then
echo 'Please use an integer value for input time' && exit 0
else
echo "inpoint ${INTIME}" >> "${IO}"
fi
fi
if [ -n "${OUTTIME}" ]; then
if ! [[ "${OUTTIME}" =~ ^-?[0-9]+$ ]] ; then
echo 'Please use an integer value for output time' && exit 0
else
if [ -n "${INTIME}" ] && ! [ "${OUTTIME}" -gt "${INTIME}" ] ; then
echo "Error! Output time must be greater than input time!" && exit 1
else
echo "outpoint ${OUTTIME}" >> "${IO}"
fi
fi
fi
#Create Fingerprint
ffmpeg -f concat -safe 0 -i "${IO}" -vf signature=format=xml:filename="${TEMPFINGERPRINT}" -map 0:v -f null -
xmlstarlet sel -N "m=urn:mpeg:mpeg7:schema:2001" -t -m "m:Mpeg7/m:DescriptionUnit/m:Descriptor/m:VideoSignatureRegion/m:VSVideoSegment" -v m:StartFrameOfSegment -o ':' -v m:EndFrameOfSegment -o ':' -m m:BagOfWords -v "translate(.,' ','')" -o ':' -b -n "${TEMPFINGERPRINT}" > "${TEMPFINGERPRINT_SORTED}"
#Sort extract relevant values from fingerprint and sort for parsing
(IFS=$'\n'
for i in $(cat "${TEMPFINGERPRINT_SORTED}") ; do
hash1=$(echo "${i}" | cut -d':' -f3)
hash2=$(echo "${i}" | cut -d':' -f4)
hash3=$(echo "${i}" | cut -d':' -f5)
hash4=$(echo "${i}" | cut -d':' -f6)
echo "SELECT objectIdentifierValue,startframe,endframe,hash1,hash2 FROM fingerprints WHERE hash1='${hash1}' AND hash2='${hash2}' AND (hash3='${hash3}' OR hash4='${hash4}')" | mysql --login-path="${PREMIS_PROFILE}" "${PREMIS_NAME}" | tr '\t' ' ' | grep -v "objectIdentifierValue" >> "${RESULTS}"
done)
echo
#Exit if no results found
if [[ -z $(cat "${RESULTS}") ]] ; then
echo "No potential matches were found." && exit 0
fi
echo "Potential matches were found in the following frame ranges:"
echo
#Loop for sorting possible matches divided by files and chunks of approximately 500 frames (Finds an input and then first output after 500)
while read -r RESULT ; do
RESULTNAME=$(echo "$RESULT" | cut -d' ' -f1)
INFRAME=$(echo "$RESULT" | cut -d' ' -f2)
OUTFRAME=$(echo "$RESULT" | cut -d' ' -f3)
HASHMATCH=$(echo "$RESULT" | cut -d' ' -f4- | tr ' ' ':')
if [ -z ${INTIME} ] ; then
INTIME=0
fi
#Checks if the result is a new file. Marks last out time for previous file and new file name.
if ! [[ "${RESULTNAME}" = "${LASTRESULTNAME}" ]] ; then
if [ -n "${FINALOUT}" ] ; then
if ! [ "${FINALOUT}" = "${LASTOUTFRAME}" ] || ! [ "${LARGEMATCH}" = 1 ]; then
echo "Out ${FINALOUT}" | tee -a "${DRAWTEXT}"
echo "outpoint $((( $(grep "${FINALHASH}" "${TEMPFINGERPRINT_SORTED}" | cut -d':' -f2 | head -n 1) / 30 ) + ${INTIME}))" >> "${VISUALRESULTS}"
fi
FINALOUT=''
FINALHASH=''
LARGEMATCH=''
fi
LASTRESULTNAME=$(echo "$RESULT" | cut -d' ' -f1)
LASTOUTFRAME=''
LASTINFRAME=''
echo | tee -a "${DRAWTEXT}"
echo "${LASTRESULTNAME}" | tee -a "${DRAWTEXT}"
echo "------" | tee -a "${DRAWTEXT}"
fi
#Checks if new frame match preceeds previous matches and resets variables
if [[ ${INFRAME} -lt ${LASTINFRAME} ]] ; then
if ! [ "${NEWIN}" = "1" ] ; then
echo "Out ${FINALOUT}" | tee -a "${DRAWTEXT}"
echo "outpoint $((($(grep "${FINALHASH}" "${TEMPFINGERPRINT_SORTED}" | cut -d':' -f2 | head -n 1) / 30 ) + ${INTIME}))" >> "${VISUALRESULTS}"
fi
LASTOUTFRAME=''
LASTINFRAME=''
SMALLFINALMATCH='1'
fi
# Checks if match is first matching chunk for that file (or after reset) and sets variable
if [ -z "${LASTINFRAME}" ] ; then
LASTINFRAME="${INFRAME}"
NEWIN=1
fi
# Sets variable if empty (first match after reset)
if [ -z "${LASTOUTFRAME}" ] ; then
LASTOUTFRAME="${OUTFRAME}"
fi
# Marks input if first match for file or after reset
if [ "${NEWIN}" = "1" ] ; then
echo "In ${INFRAME}" | tee -a "${DRAWTEXT}"
LASTINFRAME="${INFRAME}"
echo "file '${INPUT}'" >> "${VISUALRESULTS}"
echo "inpoint $((($(grep "${HASHMATCH}" "${TEMPFINGERPRINT_SORTED}" | cut -d':' -f1 | head -n 1) / 30 ) + ${INTIME}))" >> "${VISUALRESULTS}"
NEWIN=''
fi
# Marks output after 500 frame threshold is exceded
if [[ "${OUTFRAME}" -gt $(( ${LASTINFRAME} + 500 )) ]] ; then
LASTOUTFRAME="${OUTFRAME}"
NEWIN='1'
LARGEMATCH='1'
SMALLFINALMATCH=''
echo "Out ${LASTOUTFRAME}" | tee -a "${DRAWTEXT}"
echo "outpoint $((($(grep "${HASHMATCH}" "${TEMPFINGERPRINT_SORTED}" | cut -d':' -f2 | head -n 1) / 30 ) + ${INTIME}))" >> "${VISUALRESULTS}"
fi
FINALOUT="${OUTFRAME}"
FINALHASH="${HASHMATCH}"
done < <(cat "${RESULTS}" | sort -u)
#Marks the last outpoint of last file
if ! [ "${FINALOUT}" = "${LASTOUTFRAME}" ] || ! [ "${LARGEMATCH}" = 1 ] || [ "${SMALLFINALMATCH}" = 1 ] ; then
echo "Out ${FINALOUT}" | tee -a "${DRAWTEXT}"
echo "outpoint $((($(grep "${FINALHASH}" "${TEMPFINGERPRINT_SORTED}" | cut -d':' -f2 | head -n 1) / 30 ) + ${INTIME}))" >> "${VISUALRESULTS}"
fi
done
#Play footage from input for which possible matches were found
if ! [ "${MODE}" = 'text' ] ; then
ffplay -hide_banner -loglevel panic -f concat -safe 0 -i "${VISUALRESULTS}" -vf drawtext=fontcolor=white:box=1:[email protected]:fontsize=20:fontfile="/Library/Fonts/Andale Mono.ttf":textfile="${DRAWTEXT}"
fi