Scripting

需要腳本:將最新的 JPEG 轉換為影片,然後刪除舊的 JPEG

  • June 10, 2013

我有一個 IP 攝像頭,只要它檢測到它正在查看的房間中有移動,它就會將 JPEG 圖片上傳到我的 Arch Linux 盒子上的 FTP 文件夾。它每秒上傳一個 JPEG,直到所有移動活動停止。

它以下列方式命名 JPEG 文件: 在此處輸入圖像描述

剖析,意思是:

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

我想要一個可以從它們製作每秒 1 幀的影片的腳本(ffmpeg我知道很容易),但是,它必須足夠聰明,只能從彼此相距 2 秒內的圖像製作影片,然後刪除它使用的那些jpeg。如果網路延遲失去一幀,我會說“彼此相隔 2 秒”。

拍攝後 2 秒內的任何未來圖像都應成為其自己的影片。所以它基本上應該能夠從相機看到的每個運動“事件”中製作影片。

我知道這樣的程序zoneminder並且motion可以做到這一點,但我想設計一個腳本。任何想法都非常感謝。

您可以從日期生成時間戳並檢查每個文件之間的跨度。正如評論中已經提到的那樣,一個問題是夏令時——假設日期/時間是特定於語言環境的。

使用stat而不是文件名作為基礎可以幫助解決這個問題。但是,該收益取決於文件​​的上傳方式(如果保留時間戳等)

作為一個起點(這比預期的要長得多),您可以嘗試這樣的事情:

#!/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

引用自:https://unix.stackexchange.com/questions/78697