[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home] [volume] [parte]


Capitolo 769.   Elaborazione dei filmati quadro per quadro

In questo capitolo vengono mostrate delle funzioni per uno script di shell compatibile con lo standard POSIX, che hanno lo scopo di elaborare un filmato (solo video), passando per l'estrazione di ogni quadro. Per il lavoro vengono usati Transcode e ImageMagic.

769.1   Estrazione dei quadri

La funzione che viene mostrata in questa sezione, viene chiamata come nell'esempio seguente, dove si richiede di elaborare il file origine.m1v per generare una serie di immagini con file che corrispondono al modello destinazione.nnnnnn.png:

...
video_to_frame origine.m1v destinazione 25 720x576
...

Segue il testo della funzione video_to_frame:

#
# The input file must be MPEG demultiplexed!
#
video_to_frame () {
    local VIDEO_SRC="$1"
    local VIDEO_DEST="$2"
    local VIDEO_FPS="$3"
    local VIDEO_GEOMETRY="$4"
    #
    # Root file name for temporary files.
    #
    TEMPORARY=`tempfile`
    #
    # X and Y, destination video geometry.
    #
    local VIDEO_X
    local VIDEO_Y
    #
    # Source video frame rate.
    #
    local SRC_VIDEO_FPS=0
    #
    # Picture elaboration.
    #
    local PICTURE
    local PICTURE_X
    local PICTURE_Y
    local PICTURE_MOVE_X
    local PICTURE_MOVE_Y
    #
    # Frame time calculation.
    #
    local FRAME_TIME_SRC=0
    local FRAME_TIME_DEST=0
    local FRAME_TIME_DEST_TOTAL=0
    #
    # Picture counters
    #
    local COUNTER=0
    local COUNTER_STRING=""
    local PICTURE_COUNTER=0
    local PICTURE_COUNTER_STRING=0
    #
    # Get separated X and Y geometry values.
    #
    VIDEO_X=`echo $VIDEO_GEOMETRY | sed "s/x[0-9]*$//"`
    VIDEO_Y=`echo $VIDEO_GEOMETRY | sed "s/^[0-9]*x//"`
    #
    # Get source FPS.
    #
    SRC_VIDEO_FPS=`file $VIDEO_SRC | sed "s/^.* \([0-9.]*\) fps.*$/\1/"`
    #
    # Verify.
    #
    if [ "$SRC_VIDEO_FPS" = "" ]
    then
        false
        return
    fi
    #
    # Get single frames into JPG files, as temporary files.
    # It will be: $TEMPORARY.000000.jpg
    #             $TEMPORARY.000001.jpg
    #                           ...
    #
    transcode -i $VIDEO_SRC -o $TEMPORARY. -y jpg
    #
    # Convert to the destination geometry, into PNG.
    #    
    for PICTURE in $TEMPORARY.[0-9][0-9][0-9][0-9][0-9][0-9].jpg
    do
        #
        # Show something.
        #
        echo "[$0] Converting \"$PICTURE\""
        #
        # Convert to the destination geometry, but keep it in scale.
        #
        convert -scale $VIDEO_GEOMETRY $PICTURE $TEMPORARY.tmp.png
        #
        # Get geometry after conversion.
        #
        PICTURE_X=`identify $TEMPORARY.tmp.png | sed "s/^.* PNG \([0-9]*\)x\([0-9]*\).*$/\1/"`
        PICTURE_Y=`identify $TEMPORARY.tmp.png | sed "s/^.* PNG \([0-9]*\)x\([0-9]*\).*$/\2/"`
        #
        # Check if more adaptation must be done.
        #
        if [ $PICTURE_X -eq $VIDEO_X ] && [ $PICTURE_Y -eq $VIDEO_Y ]
        then
            #
            # Geometry is right.
            #
            cp $TEMPORARY.tmp.png $PICTURE.png
            #
        else
            #
            # The picture must be filled somehow.
            #
            PICTURE_MOVE_X=$((($VIDEO_X - $PICTURE_X) / 2))
            PICTURE_MOVE_Y=$((($VIDEO_Y - $PICTURE_Y) / 2))
            #
            convert -geometry $VIDEO_GEOMETRY! \
                    -fill gray \
                    -colorize 100% \
                    $PICTURE $TEMPORARY.bg.png
            #
            composite -geometry +$PICTURE_MOVE_X+$PICTURE_MOVE_Y \
                      $TEMPORARY.tmp.png \
                      $TEMPORARY.bg.png \
                      $PICTURE.png
            #
        fi
    done
    #
    # Now, we should select the frames...
    #
    if [ "$VIDEO_FPS" = "$SRC_VIDEO_FPS" ]
    then
        #
        # Just make a copy.
        #
        COUNTER=0
        while true
        do
            COUNTER_STRING=`printf "%06d" $COUNTER`
            #
            if [ -f $TEMPORARY.$COUNTER_STRING.jpg.png ]
            then
                cp $TEMPORARY.$COUNTER_STRING.jpg.png \
                   $VIDEO_DEST.$COUNTER_STRING.png
            else
                break
            fi
            COUNTER=$(($COUNTER+1))
        done
        #
    else
        #
        # Calculate the frame time.
        #
        FRAME_TIME_SRC=`echo 1 / $SRC_VIDEO_FPS | bc -l`
        FRAME_TIME_DEST=`echo 1 / $VIDEO_FPS | bc -l`
        #
        COUNTER=0
        while true
        do
            #
            # The time reference is the final frame rate.
            # The following counter is referred to the final
            # frame sequence.
            #
            COUNTER_STRING=`printf "%06d" $COUNTER`
            #
            # Calculate the total time reached at the
            # ${COUNTER}th final frame.
            #
            FRAME_TIME_DEST_TOTAL=`echo "$FRAME_TIME_DEST * $COUNTER" | bc -l`
            #
            # Calculate the right frame to take from
            # the original sequence.
            #
            PICTURE_COUNTER=`echo "$FRAME_TIME_DEST_TOTAL / $FRAME_TIME_SRC" | bc -l`
            PICTURE_COUNTER=`echo "$PICTURE_COUNTER + 0.5" | bc -l`
            PICTURE_COUNTER=`echo "$PICTURE_COUNTER" | sed "s/\.[0-9]*$//"`
            PICTURE_COUNTER_STRING=`printf "%06d" $PICTURE_COUNTER`
            #
            # Copy the selected original frame to the final
            # ${COUNTER}th frame.
            #
            if [ -f $TEMPORARY.$PICTURE_COUNTER_STRING.jpg.png ]
            then
                #
                # Show something.
                #
                echo -n "[$0] Source frame \"$PICTURE_COUNTER_STRING\" "
                echo    "to destination frame \"$COUNTER_STRING\""
                #
                # Copy.
                #
                cp $TEMPORARY.$PICTURE_COUNTER_STRING.jpg.png \
                   $VIDEO_DEST.$COUNTER_STRING.png
            else
                break
            fi
            #
            # Prepare to elaborate the next final frame.
            #
            COUNTER=$(($COUNTER+1))
        done
    fi
    #
    # Remove temporary files.
    #
    rm -f $TEMPORARY*
}

Si può sintetizzare il lavoro di questa funzione nel modo seguente:

769.2   Unione dei singoli quadri in un filmato

Dopo l'estrazione e l'adattamento dei vari quadri, si può passare alla costruzione di un nuovo filmato. Per usare la funzione che viene descritta in questa sezione, si può agire come nell'esempio seguente, dove si parte da file in formato PNG, secondo il modello origine.nnnnnn.png, per generare il file destinazione.m2v, a 25 quadri al secondo:

...
frame_to_video origine destinazione.m2v 25
...

Segue il testo della funzione frame_to_video:

#!/bin/sh
frame_to_video () {
    local VIDEO_SRC="$1"
    local VIDEO_DEST="$2"
    local VIDEO_FPS="$3"
    #
    local MPEG_TO_ENC_N
    #
    # Select NTSC or PAL for "mpeg2enc"
    #
    if   [ "$VIDEO_FPS" = "25" ]
    then
        MPEG_TO_ENC_N="p"
    else
        MPEG_TO_ENC_N="n"
    fi    
    #
    # Reassemble frames.
    #
    png2yuv -f $VIDEO_FPS -I p -L 0 -j $VIDEO_SRC.%06d.png | \
            mpeg2enc -n $MPEG_TO_ENC_N -f 3 -b 500 -q 10 -o $VIDEO_DEST
}

Appunti di informatica libera 2008 --- Copyright © 2000-2008 Daniele Giacomini -- <appunti2 (ad) gmail·com>


Dovrebbe essere possibile fare riferimento a questa pagina anche con il nome elaborazione_dei_filmati_quadro_per_quadro.htm

[successivo] [precedente] [inizio] [fine] [indice generale] [indice ridotto] [indice analitico] [home]

Valid ISO-HTML!

CSS validator!

Gjlg Metamotore e Web Directory