注釈

こんにちは、SunFounder Raspberry Pi & Arduino & ESP32 Enthusiast Community on Facebookへようこそ!他の愛好家と一緒に、Raspberry Pi、Arduino、ESP32の世界により深く入り込みましょう。

参加する理由

  • 専門家サポート: 購入後の問題や技術的な課題を、コミュニティと私たちのチームの助けを借りて解決します。

  • 学習と共有: ヒントやチュートリアルを交換して、スキルを向上させましょう。

  • 限定プレビュー: 新製品の発表や先行プレビューに早期アクセスできます。

  • 特別割引: 最新製品を特別割引でお楽しみいただけます。

  • 季節限定キャンペーンとプレゼント: プレゼント企画やホリデーキャンペーンに参加しましょう。

👉 一緒に発見し、創造する準備はできましたか? [こちら] をクリックして、今すぐ参加しましょう!

3.2 ビデオモジュール

はじめに

Raspberry Piカメラモジュールは、写真撮影だけでなく高品質な動画の録画にも対応しています。このプロジェクトでは、カメラモジュールを設定し、解像度、フレームレート、ビットレートを調整しながら動画を録画し、Raspberry Piに直接保存する方法を紹介します。


必要なもの

このプロジェクトに必要なコンポーネントは以下のとおりです。

COMPONENT INTRODUCTION

PURCHASE LINK

カメラモジュール

購入

Fusion HAT+

-

Raspberry Pi

-


実験手順

  1. カメラモジュールを便利に使用するために、パン・チルトの組み立て(カメラ用) を推奨します。

    注釈

    パンチルトを組み立てると一部のピンが隠れてしまう場合があるため、カメラを使用するときだけ組み立てるか、組み立て後に外側へ配置することをおすすめします。

    ../_images/gimbal_assemble.png
  2. Raspberry Piのデスクトップにアクセスします。

  3. ターミナルを開き、プロジェクトフォルダへ移動します。

    cd ~/ai-lab-kit/python
    
  4. 動画録画スクリプトを実行します。

    sudo python3 3.2_Video.py
    
  5. スクリプトの起動後、 Fusion HAT+ のUSRボタン を押して録画を操作します。

    ../_images/3.1_user_button1.png
    • 1回目の押下 → ライブプレビュー付きで録画開始

    • 2回目の押下 → 録画停止

    • 動画は ~/Videos ディレクトリに、次のような名前で保存されます。 video_20250101_153045.mp4

    • プログラムを終了するには、ターミナルで Ctrl+C を押します。

    ../_images/3.2_record_video.png

注釈

QTプレビューを使用するにはデスクトップ環境が必要です。 たとえばSSH経由などでプレビューを開始できない場合でも、 カメラは通常どおり動画を記録して保存できます。


コード

以下は、このプロジェクトで使用するPythonコードです。

import os
import time
import pwd
from picamera2 import Picamera2, Preview
from picamera2.encoders import H264Encoder
from picamera2.outputs import FfmpegOutput
from fusion_hat.user_button import UserButton

# ----- Paths (works correctly even when using sudo) -----
sudo_user = os.getenv("SUDO_USER")
home = pwd.getpwnam(sudo_user).pw_dir if sudo_user else os.path.expanduser("~")
videos_dir = os.path.join(home, "Videos")
os.makedirs(videos_dir, exist_ok=True)

# ----- Camera / encoder -----
camera = Picamera2()
camera.configure(camera.create_video_configuration(main={"size": (800, 600)}, controls={"FrameRate": 30}))
encoder = H264Encoder(bitrate=10_000_000)

is_recording = False
output = None
preview_started = False

def start_recording():
   """Start recording to a timestamped MP4 file."""
   global is_recording, output
   ts = time.strftime("%Y%m%d_%H%M%S")
   path = os.path.join(videos_dir, f"video_{ts}.mp4")
   output = FfmpegOutput(path)  # keep a reference while recording
   camera.start_recording(encoder, output)
   is_recording = True
   print(f"\nStart recording: {path}")

def stop_recording():
   """Stop recording safely."""
   global is_recording, output
   camera.stop_recording()
   is_recording = False
   output = None
   print("\nStop recording.")

def toggle():
   """USR button callback: toggle start/stop."""
   if not is_recording:
      start_recording()
   else:
      stop_recording()

# ----- Button -----
UserButton().set_on_click(toggle)

# ----- Preview (only if a GUI display is available) -----
if os.getenv("DISPLAY"):
   try:
      camera.start_preview(Preview.QT)
      preview_started = True
   except Exception:
      preview_started = False  # continue without preview

# ----- Run -----
camera.start()
print("Press USR to START/STOP recording. Ctrl+C to exit.")

try:
   while True:
      time.sleep(0.1)
except KeyboardInterrupt:
   pass
finally:
   # Stop recording if still active
   if is_recording:
      try:
            camera.stop_recording()
      except Exception:
            pass

   # Stop preview only if it was started
   if preview_started:
      try:
            camera.stop_preview()
      except Exception:
            pass
   try:
      camera.stop()
   except Exception:
      pass
   try:
      camera.close()
   except Exception:
      pass

コードの解説

コードの解説

  1. インポートと役割

    import os
    import time
    import pwd
    from picamera2 import Picamera2, Preview
    from picamera2.encoders import H264Encoder
    from picamera2.outputs import FfmpegOutput
    from fusion_hat.user_button import UserButton
    

    これらのモジュールは次の用途で使用されます。

    • os: 環境変数( DISPLAYSUDO_USER など)の取得やファイルパスの生成に使用します。

    • time: タイムスタンプ付きのファイル名を生成し、ループ内でプログラムを継続動作させるために使用します。

    • pwd: スクリプトを sudo で実行した場合に、実際のユーザーのホームディレクトリを取得するために使用します。

    • Picamera2 / Preview: カメラパイプラインとプレビュー機能を制御するために使用します。

    • H264Encoder: 動画フレームをH.264形式でエンコードするために使用します。

    • FfmpegOutput: エンコードされた映像をFFmpeg経由で .mp4 ファイルとして保存するために使用します。

    • UserButton: Fusion HAT+ のUSRボタンを読み取り、クリック時のコールバック関数を関連付けます。

  2. 正しい保存ディレクトリの選択(sudo対応)

    sudo_user = os.getenv("SUDO_USER")
    home = pwd.getpwnam(sudo_user).pw_dir if sudo_user else os.path.expanduser("~")
    videos_dir = os.path.join(home, "Videos")
    os.makedirs(videos_dir, exist_ok=True)
    

    この処理により、動画は実際のユーザーの ~/Videos フォルダに保存されます。

    • sudo で実行した場合、 SUDO_USER が元のユーザー名を示します。

    • pwd.getpwnam(...).pw_dir で、そのユーザーのホームディレクトリを取得します。

    • sudo を使用していない場合は、現在のユーザーのホームディレクトリ( ~ )を使います。

    • ~/Videos が存在しない場合は自動的に作成します。

  3. カメラと動画エンコーダーの初期化

    camera = Picamera2()
    camera.configure(camera.create_video_configuration(main={"size": (800, 600)}, controls={"FrameRate": 30}))
    encoder = H264Encoder(bitrate=10_000_000)
    
    • create_video_configuration(...) は、動画録画用のカメラ設定を行います。

    • size=(800, 600) は録画解像度を指定します。

    • FrameRate=30 は30 FPSで録画する設定です。

    • H264Encoder は映像を約10 MbpsのH.264形式に圧縮します。

  4. 録画状態を管理する変数

    is_recording = False
    output = None
    preview_started = False
    
    • is_recording は、現在録画中かどうかを管理します。

    • output は、録画中に FfmpegOutput オブジェクトを保持するために使用します。

    • preview_started は、プレビューウィンドウが正常に開始されたかを記録し、必要な場合のみ停止処理を行うために使用します。

  5. 録画開始処理

    def start_recording():
       """Start recording to a timestamped MP4 file."""
       global is_recording, output
       ts = time.strftime("%Y%m%d_%H%M%S")
       path = os.path.join(videos_dir, f"video_{ts}.mp4")
       output = FfmpegOutput(path)  # keep a reference while recording
       camera.start_recording(encoder, output)
       is_recording = True
       print(f"\nStart recording: {path}")
    

    録画を開始すると、次の処理が行われます。

    • タイムスタンプ付きのファイル名を生成します(例: video_20260203_154500.mp4)。

    • そのファイルに対応する FfmpegOutput を作成します。

    • camera.start_recording(...) により、動画のエンコードと保存を開始します。

  6. 録画停止処理

    def stop_recording():
       """Stop recording safely."""
       global is_recording, output
       camera.stop_recording()
       is_recording = False
       output = None
       print("\nStop recording.")
    

    録画を停止すると、次の処理が行われます。

    • camera.stop_recording() により、出力ファイルを正しく終了します。

    • output の参照を解除し、オブジェクトを解放できるようにします。

  7. USRボタンによる録画切り替え

    def toggle():
        if not is_recording:
            start_recording()
        else:
            stop_recording()
    
    UserButton().set_on_click(toggle)
    

    Fusion HAT+ のUSRボタンを押すたびに録画状態が切り替わります。

    • 1回目の押下 → 録画開始

    • 2回目の押下 → 録画停止

  8. プレビュー処理(画面あり/なし両対応)

    if os.getenv("DISPLAY"):
        try:
            camera.start_preview(Preview.QT)
            preview_started = True
        except Exception:
            preview_started = False
    
    • デスクトップGUIが利用可能な場合( DISPLAY が設定されている場合)、QTプレビューを開始しようとします。

    • 画面やGUIが利用できない場合(X11なしのSSHなど)は、プレビューを開始せず、安全にそのまま録画のみを続行します。

  9. メインループと安全な終了処理(Ctrl+C)

    camera.start()
    try:
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        pass
    finally:
        if is_recording:
            camera.stop_recording()
        if preview_started:
            camera.stop_preview()
        camera.stop()
        camera.close()
    
    • camera.start() でカメラパイプラインを開始します。

    • ループによってスクリプトを継続動作させ、ボタン入力を待ちます。

    • Ctrl+C が押されると、 finally ブロックが実行されます。

      • 録画中であれば録画を停止します(破損した動画ファイルを防ぎます)。

      • プレビューが開始されていた場合のみ、プレビューを停止します。

      • カメラを停止して閉じ、ハードウェアリソースを安全に解放します。


トラブルシューティング

  1. プレビューウィンドウが表示されない

    • 原因: デスクトップ環境なしで実行している、またはPicamera2のGUIサポートが不足している可能性があります。

    • 対処方法: Raspberry Pi Desktop/VNCを使用し、Picamera2をインストールしてください。

    sudo apt install -y python3-picamera2
    
  2. USRボタンが動作しない

    • 原因: Fusion HAT+ が正しく接続されていない、または権限が不足している可能性があります。

    • 対処方法: HATを差し直し、 sudo でスクリプトを実行し、必要に応じて toggle_recording() にデバッグ出力を追加してください。

  3. 動画が保存されない

    • 原因: sudo 使用時にホームディレクトリが正しく解決されていない、または ~/Videos フォルダが存在しない可能性があります。

    • 対処方法: REAL_USERVIDEOS_DIR の値を確認してください。 ~/Videos が存在し、書き込み可能であることを確認してください。

  4. 録画が意図せず開始/停止する

    • 原因: 他のプロセスがカメラを使用している、またはシステム負荷が高い可能性があります。

    • 対処方法: 他のカメラアプリを終了し、Raspberry Piを再起動し、 ffmpeg がインストールされていることを確認してください。

  5. ファイルが正常に確定されない

    • 原因: 録画停止前にスクリプトが強制終了された可能性があります。

    • 対処方法: 必ず Ctrl+C で終了し、スクリプトが録画を正常に停止できるようにしてください。


まとめ

このスクリプトでは、Fusion HAT+ のUSRボタンを使って動画の録画開始・停止を行いながら、ライブプレビューを表示できます。録画された動画は、自動的にタイムスタンプ付きファイル名で ~/Videos に保存されます。

ボタン操作による動画撮影のシンプルな基盤として活用でき、DIYカメラ、授業でのデモ、センサー連動型の録画プロジェクトなどへ発展させることができます。