summaryrefslogtreecommitdiffstats
path: root/abs/core/linhes-scripts/screenshooter.sh
blob: 1cb7a78890c4bba99a701ac46197d2306967fda5 (plain)
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
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#!/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