6月のブログ「ネットワークカメラの映像をラズパイでモニタする」の後、ChatGPTがGPT5になり、さらに相談し、検討しました。
結論としては、pythonのスクリプトにすることで、遅延せず、軽く落ちないシステムになりました。
Raspberry Pi zero Wでも問題なく動いたので備忘録として残します。
1.Pi zero Wの初期設定
①Pi OSの通常版(Bookworm)をインストールし、GUIでWiFiや各初期設定をしておきます。Desktopが普通に使える設定にできた後、raspi-configでCUIにします。
②CUIでHDMIから音が出るか確認します。GUIで音がでてもCUIでは設定が別なようです。
speaker-test -c1 -twav
音が出ない場合はalsaやpulseaudioの設定を確認してください。(ChatGPTに聞けば教えてくれます)
2.pythonのgstライブラリを追加
下記でライブラリを追加してください。
sudo apt install -y \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
gstreamer1.0-libav
3.pythonスクリプト
下記のrtsp-tee.pyファイルをつくります。カメラのadminパスワード、ip address、rtsp番号(26112)は適宜修正してください。
import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst, GLib
def on_message(bus, message, loop):
msg_type = message.type
if msg_type == Gst.MessageType.EOS:
print("End-of-Stream")
loop.quit()
elif msg_type == Gst.MessageType.ERROR:
err, debug = message.parse_error()
print(f"Error: {err}: {debug}")
loop.quit()
Gst.init(None)
pipeline = Gst.parse_launch(
'rtspsrc location=rtsp://admin:xxxx@192.168.xxx.xxx:26112/ipcam_h264.sdp '
'latency=0 protocols=tcp name=src '
# 映像パイプライン
'src. ! rtph264depay ! avdec_h264 ! queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 '
'! videoconvert ! autovideosink sync=false '
# 音声パイプライン
'src. ! rtpmp4gdepay ! avdec_aac ! queue max-size-buffers=0 max-size-bytes=0 max-size-time=0 '
'! audioconvert ! audioresample ! alsasink sync=false'
)
bus = pipeline.get_bus()
loop = GLib.MainLoop()
bus.add_signal_watch()
bus.connect("message", on_message, loop)
pipeline.set_state(Gst.State.PLAYING)
try:
loop.run()
except KeyboardInterrupt:
print("Stopping...")
pipeline.set_state(Gst.State.NULL)
下記の実行でカメラのモニタ画像がTVにうつるはずです。
$python3 rtsp-tee.py
4.shellスクリプト
それでも、ネットワークが切れたり、カメラ遅延の理由でpythonが落ちることがあります。
shellのスクリプトでretryやrebootでカバーします。
ファイル名は適宜修正してください。
#!/bin/bash
# ログ保存先
LOGDIR="/home/xxx/log/rtsp"
mkdir -p "$LOGDIR"
cd /home/xxx
export GST_PLUGIN_FEATURE_RANK=avdec_h264:MAX,v4l2h264dec:NONE
export GST_DEBUG=rtsp*:3,uridecodebin*:3
# ログファイル名
LOGFILE="$LOGDIR/tee.log"
# 古いログをローテーション(任意)
[ -f "$LOGFILE" ] && mv "$LOGFILE" "$LOGFILE.$(date +%Y%m%d%H%M%S)"
echo "$(date) shell start" | tee -a "$LOGFILE"
# ネットワーク接続確認(初回)
until ping -c1 192.168.24.1 >/dev/null 2>&1; do
sleep 1
done
# 監視対象のエラーパターン
ERROR_PATTERNS=("Streaming stopped" "Internal data stream error" "GLib-GObject-CRITICAL" "GStreamer-CRITICAL" "gst-resource-error")
# メインループ
while true; do
echo "$(date) gstl start" | tee -a "$LOGFILE"
# ---- Ping 遅延のログ記録部分(6ms以上)----
PING_RESULT=$(ping -c1 -W1 192.168.24.xxx | grep 'time=')
if [[ $PING_RESULT =~ time=([0-9.]+) ]]; then
RTT=${BASH_REMATCH[1]}
if (( $(echo "$RTT > 6" | bc -l) )); then
echo "$(date) [WARN] Ping delay: ${RTT} ms" | tee -a "$LOGFILE"
fi
else
echo "$(date) [ERROR] No ping reply from 192.168.24.xxx" | tee -a "$LOGFILE"
fi
# ----------------------------------------------
python3 rtsp-tee.py >> "$LOGFILE"
echo "$(date) tee exited with status $?" | tee -a "$LOGFILE"
# エラーパターン検出で再起動
for pattern in "${ERROR_PATTERNS[@]}"; do
if tail -n 100 "$LOGFILE" | grep -q "$pattern"; then
echo "$(date) [FATAL] Detected critical error: '$pattern' ? Rebooting..." | tee -a "$LOGFILE"
sudo reboot
fi
done
sleep 3
done
echo "$(date) tee stop" | tee -a "$LOGFILE"
シェルの自動起動はsystemctlに登録しました。
登録の仕方もChatGPTに聞けば教えてくれます。
1. サービスファイルを作成
サービスは通常 /etc/systemd/system/ に置きます。
例:/etc/systemd/system/myapp.service
[Unit]
Description=My Python App
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/myapp.py
WorkingDirectory=/home/pi
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
ポイント:
ExecStart= に実行するコマンド(フルパス)を書く
User= に実行ユーザー(例: pi)を書く
Restart=always で落ちても再起動する
2. systemd に認識させる
sudo systemctl daemon-reload
3. サービスを有効化
起動テスト:
sudo systemctl start myapp.service
状態確認:
systemctl status myapp.service
自動起動設定:
sudo systemctl enable myapp.service
アイオーのネットワークカメラでは、HD画質でのweb再生(常時モニタ)は2台までですが、ラズパイの場合はそのような制限はないようです(多数接続すると遅延がおきるかも)
コメントお待ちしております。
コメントを残す