Precisa de script: os mais recentes JPEGs para vídeo e, em seguida, exclua JPEGs antigos

3

Eu tenho uma câmera IP que envia imagens JPEG para uma pasta FTP na minha caixa Arch Linux sempre que detecta movimento na sala em que está olhando. Carrega um JPEG a cada segundo até que toda a atividade de movimento pare.

Nomeia os arquivos JPEG da seguinte maneira:

Dissecado,issosignifica:

name-of-camera(inside)_1_YEAR-MONTH-DATE-TIME-SECONDS_imagenumber.jpg

Euqueroumscriptquepossafazerumvídeode1quadroporsegundodeles(fácilcomffmpegeusei),MAS,eledeveserinteligenteosuficienteparafazerovídeosomenteapartirdasimagensqueestãodentrode2segundosunsdosoutros,emseguida,excluaosjpegsqueeleusou.Eudigo"2 segundos um do outro" no caso de latência de rede onde falta um quadro.

Todas as imagens futuras que estão dentro de 2 segundos após serem tiradas, devem se tornar seu próprio vídeo. Então, basicamente, deve ser capaz de fazer vídeos de cada "evento" de movimento que a câmera viu.

Eu sei que programas como zoneminder e motion podem fazer isso, mas quero criar um script em vez disso. Alguma idéia muito apreciada.

    
por nLinked 08.06.2013 / 14:06

1 resposta

2

Você pode gerar o registro de data e hora a partir da data e verificar o intervalo entre cada arquivo. Um problema, como já mencionado nos comentários, é a economia de horário de verão - supondo que a data / hora seja específica do local.

Usar stat em vez de nomes de arquivos como base pode ajudar nisso. Mas, esse ganho depende de como os arquivos são carregados (se os timestamps são preservados, etc.)

Como ponto de partida (isso se tornou muito mais longo do que o esperado), você poderia tentar algo assim:

#!/bin/bash

declare -a fa_tmp=()    # Array holding tmp files with jpg collections.
declare dd=""           # Date extracted form file name.
declare -i ts=0         # Time stamp from date.
declare -i pre=0        # Previous time stamp.
declare -i lim=2        # Limit in seconds triggering new collection.
fmt_base='+%F-%H_%M_%S' # Format for date to generate video file name.

# Perhaps better using date from file-name:
# export TZ=UTC
# stat --printf=%Y $f

# Loop all jpg files
for f in *.jpg; do
    # Extract date, optionally use mktime() with gawk.
    # This assumes XX_XX_DATETIME_XXX... by split on underscore.
    dd=$(printf "$f" | tr '_' ' ' | awk '{
    printf("%d-%02d-%02d %02d:%02d:%02d",
        substr($3,  1, 4),
        substr($3,  5, 2),
        substr($3,  7, 2),
        substr($3,  9, 2),
        substr($3, 11, 2),
        substr($3, 13, 2))
    }')

    # Create time stamp from date.
    ts=$(date +%s -d "$dd")

    # If duration is greater then lim, create new tmp file.
    if ((ts - pre > lim)); then
        f_tmp="$(mktemp)"
        fa_tmp+=("$f_tmp")
        # First line in tmp file is first time stamp.
        printf "%s\n" "$ts" >> "$f_tmp"
    fi

    # Add filename to current tmp file.
    printf "%s\n" "$f" >> "$f_tmp"

    # Previous is current.
    pre="$ts"
done

declare -i i=1
# Loop tmp files.
for f_tmp in "${fa_tmp[@]}"; do
    printf "PROCESSING: %s\n---------------------------\n" "$f_tmp"
    base=""
    i=1

    # Rename files.
    while read -r img; do
        # First line is time stamp and is used as base for name.
        if [[ "$base" == "" ]]; then
            base=$(date "$fmt_base" -d "@$img")
            continue
        fi
        # New image name.
        iname=$(printf "%s-%04d.jpg" "$base" "$i")
        echo "mv '$img' => '$iname'"
        mv "$img" "$iname"
        ((++i))
    done <"$f_tmp"

    # Generate video.
    if ffmpeg -f image2 \
        -framerate 3 \
        -pattern_type sequence \
        -start_number 1 \
        -i "$base-%04d.jpg" \
        -vcodec mpeg4 \
        -r 6 \
        "$base.mp4"; then

        # Iff success, move jpg's to backup folder.
        mkdir "$base"
        mv $base-*.jpg "$base"
    else
        printf "FAILED:\n" >&2
        ls $base-*.jpg >&2
    fi

    # Remove tmp file.
    rm "$f_tmp"
done
    
por 10.06.2013 / 09:55