Permalink
Fetching contributors…
Cannot retrieve contributors at this time
executable file 179 lines (160 sloc) 7.06 KB
#!/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:boxcolor=black@.4:fontsize=20:fontfile="/Library/Fonts/Andale Mono.ttf":textfile="${DRAWTEXT}"
fi