#!/bin/bash # Written by Bob Igo from the MythTV Store at http://MythiC.TV # with contributions from TJC and Sarah Hayes # Email: bob@stormlogic.com # # If you run into problems with this script, please send me email # # Maintained by Michael Hanson <mihanson@linhes.org> # # This is alpha code to auto-generate thumbnails for previews in MythVideo. # It won't currently work on some filenames that have spaces in them. # It's surely just a matter of escaping or quoting, but I have yet to find # the right incantation. # example usage: # find -L /myth/video -wholename '*.covers' -prune -o -name '*.resume' -o -type f -exec screenshooter.sh -v {} \; # limitations: # -- # In an MBE/SBE/FE setup this might get the settings for the wrong machine... # The script has no AI to know if a grabbed frame is useful to identify the video, only that it was able to grab it. # Doesn't clean up after itself if videos are deleted, though MythTV may do this on its own. # Minimum theoretical compatible video length is 4 seconds. Shorter videos will not work with this version. # Surely more limitations I can't think of because it's my baby :) Usage() { echo "USAGE:" echo `basename $0` "-f FILENAME [-s SECONDS] [-c] [-b HOSTNAME] [-u USERNAME] [-p PASSWORD] [-v]" echo "-f: video filename" echo "-s: number of Seconds to skip before capturing (270 by default)" echo "-c: Clobber any previous screenshot found for this video (off by default)" echo "-b: mysql server (Backend) hostname (default: dbhost in /etc/systemconfig)" echo "-u: mysql Username (mythtv by default)" echo "-p: mysql Password (mythtv by default)" echo "-v: verbose mode (off by default)" echo "-x: check for valid video eXtension (off by default)" echo echo "EXAMPLE: $0 -f shuttle.mpg -c -s 30" exit 3 } . /etc/systemconfig if [ -z $1 ]; then Usage fi F_MISSING=1 while getopts "f:sbupvcx" FLAG ; do case "$FLAG" in f) FILENAME="$OPTARG" F_MISSING=0;; s) SKIPAHEAD="$OPTARG";; c) CLOBBER=1;; b) BACKEND_HOSTNAME="$OPTARG";; u) DBUSERNAME="$OPTARG";; p) DBPASSWORD="$OPTARG";; v) VERBOSE=1;; x) EXTENSION_CHECK=1;; *) Usage;; esac done if [ $F_MISSING == 1 ]; then Usage fi # Declaring Variables here and assigning sensible defaults. # SKIPAHEAD is the number of seconds to skip ahead before starting the frame capture. # Set it to an arbitrary value if none is specified. SKIPAHEAD=${SKIPAHEAD:-"270"} BACKEND_HOSTNAME=${BACKEND_HOSTNAME:-${dbhost}} DBUSERNAME=${DBUSERNAME:-"mythtv"} DBPASSWORD=${DBPASSWORD:-"mythtv"} # Defaults to quiet. VERBOSE=${VERBOSE:-0} # Unless otherwise told, do not clobber existing cover files. CLOBBER=${CLOBBER:-0} # Unless otherwise told, do not check the file extension against # MythTV's list of registered video file types. EXTENSION_CHECK=${EXTENSION_CHECK:-0} SG_VIDEOS=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \ "SELECT dirname FROM storagegroup WHERE groupname='Videos'") if [ ! -d "${SG_VIDEOS}" ] ; then echo "Directory $SG_VIDEOS does not exist, nowhere to put the screen shot!" echo "Have you configured Storage Groups yet?" exit 1 fi SG_SCREEN=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \ "SELECT dirname FROM storagegroup WHERE groupname='Screenshots'") if [ ! -d "${SG_SCREEN}" ] ; then echo "Directory $SG_SCREEN does not exist, nowhere to put the screen shot!" echo "Have you configured Storage Groups yet?" exit 1 fi VIDEO_EXTENSION=${FILENAME##*.} # Since we cron'd lets first make sure the validity of the file if [ "$EXTENSION_CHECK" == "1" ]; then EXCHECK=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe "select f_ignore from videotypes where extension='${VIDEO_EXTENSION}';") #excheck returns blank, it found nothing. if [ "$EXCHECK" == "" ]; then if [ "$VERBOSE" == "1" ]; then echo "$VIDEO_EXTENSION does not appear to be a valid media file, skipping." fi exit 1 else # It is valid, but should we ignore it. If so then excheck will equal 1. if [ "EXCHECK" == "1" ]; then if [ "$VERBOSE" == "1" ]; then echo "$VIDEO_EXTENSION is set to ignore." fi exit 1 fi # It is valid, it's not set to ignore. if [ "$VERBOSE" == "1" ]; then echo "$VIDEO_EXTENSION appears in the Database, checking further." fi EXCHECK=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe "select title from videometadata where filename LIKE '%${FILENAME}';") #Right, the file is supposed to be playable. Has it been imported to the Db yet? if [ "$EXCHECK" == "" ] ; then if [ "$VERBOSE" == "1" ]; then echo "$VIDEO_FILENAME does not exist in the database." fi exit 1 fi fi fi if [ "$CLOBBER" -eq 0 ]; then # Since we're not clobbering, first check to see if this video already has a coverfile entry in MySQL: SQL_CMD="SELECT coverfile FROM videometadata WHERE filename LIKE '%${FILENAME}';" CURRENT_COVERFILE=`mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -B -e "$SQL_CMD" | tail -1` if [[ "$CURRENT_COVERFILE" != "" ]] && [[ "$CURRENT_COVERFILE" != " " ]] && [[ "$CURRENT_COVERFILE" != "No Cover" ]]; then # there's already a cover file for this video if [ "$VERBOSE" == "1" ]; then echo "$FILENAME has cover file, skipping." fi exit 2 fi fi # Swap the video file extension for png. Should work assuming the extension only appears ONCE! VIDEO_CAPTURE_PATHNAME="$SG_SCREEN/${FILENAME%.*}.png" # How many frames of video to capture. We'll grab the last frame as our screenshot. if [ "$VIDEO_EXTENSION" == "m4v" ]; then FRAMES_TO_CAPTURE="90" else FRAMES_TO_CAPTURE="05" fi SHOTFILE="000000"$FRAMES_TO_CAPTURE".png" VIDEO_STATS="/tmp/screenshooter_video_stats.txt" # Get the full path of the video file, less the storage group prefix FULL_PATH=$(mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -sNBe \ "SELECT filename FROM videometadata WHERE filename LIKE '%${FILENAME}';") cd /tmp # The video we're processing may be shorter than SKIPAHEAD seconds. # Keep trying to capture until we find a SKIPAHEAD value within the length of the video. # Give up if we reach 0 seconds. while [ ! -f "$SHOTFILE" ]; do /usr/bin/mplayer -ss $SKIPAHEAD -vf scale=640:-2 -ao null -vo png -quiet -frames $FRAMES_TO_CAPTURE -identify "$SG_VIDEOS/$FULL_PATH" &> $VIDEO_STATS & TIMEOUT=9 # Some video formats will play audio only. This loop gives the above command 20 seconds to # finish, otherwise it gets killed. while [ -n "`ps -p $! --no-heading`" ]; do TIMEOUT=$(expr $TIMEOUT - 1) if [ "$TIMEOUT" -le 0 ]; then kill -9 $! break fi sleep 1 done SKIPAHEAD=$(expr $SKIPAHEAD / 2) if [ "$SKIPAHEAD" -le 0 ]; then break fi done if [ -f "$SHOTFILE" ]; then # Now, the video_capture is taken, and the name of the shot is in $SHOTFILE # Rename it and move it to the place where video_captures live. /bin/mv -f "$SHOTFILE" "$VIDEO_CAPTURE_PATHNAME" /bin/rm -f 000000*png chown mythtv: "$VIDEO_CAPTURE_PATHNAME" # We've got the shotfile nailed, now calculate video run length. VIDEO_LENGTH_IN_SECONDS=`grep ID_LENGTH $VIDEO_STATS | awk -F'=' '{print $2}'` VIDEO_LENGTH_IN_INTEGER_SECONDS=${VIDEO_LENGTH_IN_SECONDS/%.*/} if [ $VIDEO_LENGTH_IN_INTEGER_SECONDS -lt 60 ]; then VIDEO_LENGTH_IN_MINUTES="1" else VIDEO_LENGTH_IN_MINUTES=$(expr $VIDEO_LENGTH_IN_INTEGER_SECONDS / 60) fi SQL_CMD="UPDATE videometadata SET length = '${MIN_LENGTH}' WHERE filename LIKE '%$FILENAME';" mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -e "$SQL_CMD" # put the screenshot pathname and any runlength info into videometadatatable # Pre-escape any single or double quotes for the SQL command. VIDEO_CAPTURE_PATHNAME=`echo $VIDEO_CAPTURE_PATHNAME | sed -e "s/'/\\\'/g" -e 's/"/\\\"/g' ` FILENAME=`echo $FILENAME | sed -e "s/'/\\\'/g" -e 's/"/\\\"/g' ` SQL_CMD="UPDATE videometadata SET coverfile = '${VIDEO_CAPTURE_PATHNAME}', length = '${VIDEO_LENGTH_IN_MINUTES}' WHERE filename LIKE '%${FILENAME}';" mysql -u $DBUSERNAME -p$DBPASSWORD -h $BACKEND_HOSTNAME -D mythconverg -e "$SQL_CMD" else echo "No image could be captured from $FILENAME" exit 1 fi