ラズパイzero で音声つき動画の自動撮影
ダイソーの300円で販売されているAB Shutter3 で
撮影とシャットダウンボタンを作成する予定だったが
ボタンが1つしか認識しないため
撮影については cron で行い
シャットダウンについては
AB Shutter3 で担当することに
motion の自動起動を停止
これは
insservの使い方
を参考に
insserv -r motion
で停止
sudo service motion stop
も実行
これをしないとどんどん静止画が増えてしまう
次に
1 | nano bluebutton.sh |
でファイルを作成
1 2 3 | #!/bin/sh command = "sudo bluebutton -d=" Shutter3 " -c ~/.config/bluebutton" eval $ command |
として保存
1 | sudo crontab -e |
でファイルを開き
以前
1 | #*/10 * * * * /home/pi/rscamera.sh |
としていたのでこれをコメントアウト
@reboot /home/pi/bluebutton.sh
を追記
これで再起動したときに
AB Shutter3 が有効化される
これを行ったため
マイクの情報が変わっていた
arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 2: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio]
サブデバイス: 0/1
サブデバイス #0: subdevice #0
amixer -c2
Simple mixer control ‘Mic’,0
Capabilities: cvolume cvolume-joined cswitch cswitch-joined
Capture channels: Mono
Limits: Capture 0 – 16
Mono: Capture 16 [100%] [23.81dB] [on]
Simple mixer control ‘Auto Gain Control’,0
Capabilities: pswitch pswitch-joined
Playback channels: Mono
Mono: Playback [on]
このため音声つき動画撮影コマンドも変更され
timeout 15 raspivid -t 0 -w 640 -h 480 -b 10000000 -fps 30 -awb fluorescent -n -o test.h264 | arecord -D hw:2,0 -f S16_LE -r 44100 -d 0 test.wav;ffmpeg -y -i test.wav -r 30 -i test.h264 -vcodec copy /mnt/nas/test.mk
となる
このままだと同じファイルになってしまうので
dateコマンドを使って作成するファイルに日時と時間をつける
にdate コマンドの解説があるのでこちらを参考に
1 | timeout 15 raspivid -t 0 -w 640 -h 480 -b 10000000 -fps 30 -awb fluorescent -n -o test .h264 | arecord -D hw:2,0 -f S16_LE -r 44100 -d 0 test .wav;ffmpeg -y -i test .wav -r 30 -i test .h264 -vcodec copy /mnt/nas/ ` date +%Y%m%d_%H-%M-%S`.mkv |
とすれば
ファイル名が
20200913_21-01-32.mkv
というように
秒数まで入るので上書きされることがなくなる
%Yで西暦
%m で月
%d で日
%H が時間
%M が分
%S で秒
となっている
なお
1 | ` date +%Y%m%d_%H-%M-%S` |
はバッククォートで囲っている
shift + @ でバッククォートになる
‘ と似ているので注意
あとはラズパイzero の時間がずれているので
Raspberry Pi のシステム時刻を変更する
によれば初期状態だと世界標準になっているとのこと
1 | sudo timedatectl set -timezone Asia /Tokyo |
を実行すれば再起動するまで一時的に合わせることができるので
起動時にこれを実行するようにする
1 2 | cd /etc/init .d/ sudo nano autorun_date |
でスクリプトファイルを作成
1 2 3 4 5 6 7 8 9 10 11 12 13 | ] #!/bin/sh ### BEGIN INIT INFO # Provides: mathkernel # Required-Start: $local_fs # Required-Stop: $local_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: mathkernel ### END INIT INFO #システム時刻を日本に合わせる sudo timedatectl set -timezone Asia /Tokyo |
として保存
1 | sudo chmod 755 autorun_date |
で実行権限付与
本来ならこれをスクリプトとして登録するところだったけど
現在では
【CentOS7】timedatectlコマンドでタイムゾーンをJSTへ変更する
にあるように
一度コマンドを実行すれば設定はそのままになるようになっていた
なお
1 | sudo timedatectl |
を実行すると
現在設定されているタイムゾーンを確認できる
今回は
1 2 3 4 5 6 7 | Local time : 金 2020-09-18 05:51:10 JST Universal time : 木 2020-09-17 20:51:10 UTC RTC time : n /a Time zone: Asia /Tokyo (JST, +0900) Network time on: yes NTP synchronized: yes RTC in local TZ: no |
となっていた
次に音声つき動画撮影のスクリプトを用意
とはいってもこれをスクリプトファイルにするだけ
1 | nano homevideo.sh |
でファイルを作成
1 2 | #!/bin/bash timeout 15 raspivid -t 0 -w 640 -h 480 -b 10000000 -fps 30 -awb fluorescent -n -o test .h264 | arecord -D hw:2,0 -f S16_LE -r 44100 -d 0 test .wav;ffmpeg -y -i test .wav -r 30 -i test .h264 -vcodec copy /mnt/nas/ ` date +%Y%m%d_%H-%M-%S`.mkv |
として保存
1 | chmod +x homevideo.sh |
で実行権限付与
1 | . /homevideo .sh |
としたが
timeout コマンドが動作しない
や
bashのtimeoutコマンドをshellスクリプトから実行すると終了ステータスが正しく取得できない
をみたところ
スクリプトファイルを timeout コマンドで実行すればよさそう
なおワンライナーでの書き方については
(Linux)コマンドを連結して行う「;」「&」「&&」「||」の違い
を参考に
そのままワンライナーを書き込んでも失敗するため
1 2 3 | #!/bin/bash raspivid -t 0 -w 640 -h 480 -b 10000000 -fps 30 -awb fluorescent -n -o test .h26$ ffmpeg -y -i test .wav -r 30 -i test .h264 -vcodec copy /mnt/nas/ ` date +%Y%m%d_$ |
として保存
変更点は ; による1行の部分を
; を削除して2行にしている
1 | timeout 15 . /homevideo .sh |
としたが
timeout コマンドにより変換する前に停止してしまう
とりあえずcrontab に直接コマンドを書き込むことにしたが
これもダメ
を元に考えてみると
timeoutはコマンドであるため
bashシェルのサブプロセスで実行される
timeoutコマンドは
タイムアウトのサブプロセス(シェルの孫プロセス)として実行さる
つまり timeout コマンドをシェルスクリプトでそのまま使うことは無理そう
を参考に
同じ機能をもったシェル関数を作成し
それを実行
ラズパイzero にexpect コマンドがなかったので
1 | sudo apt-get install expect |
でインストール
あとは
homevideo.sh の内容を
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/bin/bash limittime() { time =$1 # start the command in a subshell to avoid problem with pipes # (spawn accepts one command) command = "/bin/sh -c \"${@:2}\"" expect -c "set timeout $time; spawn -noecho $command; expect timeout { exit 124 } eof; catch wait result; exit [lindex \$result 3]" } limittime 15 raspivid -t 0 -w 640 -h 480 -b 10000000 -fps 30 -awb fluorescent -n -o test .h264 | limittime 15 arecord -D hw:2,0 -f S16_LE -r 44100 -d 0 test .wav ffmpeg -y -i test .wav -r 30 -i test .h264 -vcodec copy /mnt/nas/ ` date +%Y%m%d_%H-%M-%S`.mkv |
として
raspivid と arecord を
15秒後に終わるように指定
コマンドのときには raspivid のみ timeoutコマンドを実行すれば
成功したけど
シェルスクリプトで実行するときには
arecord コマンドも設定しないとオーバーランになってしまい
ctrl+c で止めるまで動画変換されなかった
シェルスクリプトで音声つき動画がとれるようになったので
これを cron で実行
1 | crontab -e |
を実行
最終行に
1 | * /2 * * * * /home/pi/homevideo .sh |
を追記して保存
これで2分ごとに15秒の音声つき動画が撮影されるようになる
間隔をおいてのcron 実行については
を参考に