Scripting
需要腳本:將最新的 JPEG 轉換為影片,然後刪除舊的 JPEG
我有一個 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