Video-Thumbnails für WD TV Live erstellen

Januar 17, 2010

Mein neues Spielzeug, der WD TV Live, kann Thumbnails (Vorschau-Bilder) zu einer Video-Datei anzeigen, wenn im selben Ordner eine jpg-Datei (am besten mit 120×180 Pixeln) mit dem selben Namen wie das Video liegt. Zur Datei video.mkv wird also z.B. video.jpg angezeigt.

Ich hab mir also ein Shell-Script besorgt, dass aus den Videos automatisch die Bilder generiert. Ich hab mich da für Sekunde 45 entschieden, weil bei einigen Filmen ganz am Anfang ja erstmal nutzlose Trailer der beteiligten Unternehmen laufen… Weil es vor a120llem bei 720p- oder 1080p-Videos ne Weile dauern kann, bis da ein einzelnes Bild generiert ist, hab ich dann (weil ich nicht so lang warten wollte ;) heute ein Shell-Script geschrieben, das vier Dateien auf einmal abarbeitet (ich hab nen Quad-Core). Das Script sollte man auch ohne allzu großen Aufwand anpassen können, dass es andere Aufgaben mit mehr oder weniger gleichzeitigen Jobs parallel abarbeitet (bald vielleicht auch meine Log-Files…).

Vorraussetzungen: ffmpeg, imagemagick

#!/bin/bash
#set -x

# file types:
TYPES='.+\.(mkv|avi|mpg|mpeg|mov|wmv|mp4|flv)$'
# make thumbnail at second ## of the movie
OFFSET=45
# number of parallel processes
WORKERS=4

NL='
'

queue_put() {
 queue_name=$1
 value=$2
 if [ -n "${!queue_name}" ]; then
 queue_val="${!queue_name}"
 eval "$queue_name=\"$queue_val$NL$value\""
 #read $queue_name <<< "$queue_val$NL$value"
 else
 read $queue_name <<< "$value"
 fi
}
queue_pop() {
 queue_name=$1
 var=$2

 queue="${!queue_name}"
 if [ -n "$queue" ]; then
 index=$(expr index "$queue" "$NL")

 read $var <<< "${queue%%$NL*}"
 if [ $index -eq 0 ]; then
 read $queue_name <<< ''
 else
 eval "$queue_name=\"${queue#*$NL}\""
#        read $queue_name <<< "${queue#*$NL}"
 fi
 fi
}

echo "searching for missing thumbnails..."

allfiles=$(find . -regextype posix-extended -iregex "$TYPES" -exec /bin/bash -c "file=\"{}\"; exit \$(test ! -f \"\${file%.*}.jpg\")" \; -printf '%p\n')

dir=$(mktemp -d)

work() {
    echo "worker $workerid is starting up..."
    sleep .25

    pipe="$dir/job$workerid"
    while [ -p "$pipe" ]; do
        echo READY > "$pipe"
        read file < "$pipe"
        if [ "$file" = "DONE" ]; then
            echo "worker $workerid is shutting down."
            exit 0
        fi

        thumb=${file%.*}.jpg

        echo
        echo
        echo
        echo "worker $workerid processing $file..."
        ffmpeg -itsoffset -$OFFSET -i "$file" -vcodec mjpeg -vframes 1 -an -f rawvideo -y -v -1 "$thumb"
        mogrify -resize 120x180 "$thumb"
    done
    return 0
}

masterpid=$$

workerid=0
workers=( )
while [ $workerid -lt $WORKERS ]; do
    mkfifo "$dir/job$workerid"
    work &
    workers[$workerid]=$!

    let workerid++
done

sleep 3
while [ -n "$allfiles" ]; do
    workerid=0
    while [ -n "$allfiles" -a $workerid -lt $WORKERS ]; do
        pipe="$dir/job$workerid"
        if [ -p $pipe ]; then
            response=$(cat < $pipe)
             if [ "$response" = "READY" ]; then
                 queue_pop allfiles file
                 echo $file > "$pipe"
            fi
        fi
        let workerid++
    done

    sleep .25
done

workerid=0
while [ $workerid -lt $WORKERS ]; do
    cat "$dir/job$workerid" > /dev/null
    echo DONE > "$dir/job$workerid"
    wait ${workers[$workerid]}

    let workerid++
done

rm -rf "$dir"

Übrigens: Ordnern kann man mit einem folder.jpg ein Bild zuordnen.

Leave a Reply