📹

Raspberry Pi + Camera Module でRTSPネットワークカメラを作る

2024/05/01に公開

旧rtsp-simple-serverであるMediaMTXを使って構築します。

前提条件

  • Raspberry Pi 4 B 8GB
  • Raspbian bookworm Desktop 64bit
  • Camera Module 3

下準備

必要ライブラリのインストール

sudo apt install libcamera-dev libfreetype-dev xxd git

Goのインストール

https://go.dev/dl/

64bit OSなので、go1.xx.x.linux-arm64.tar.gzをダウンロードします。32bit OSの場合はgo1.xx.x.linux-armv6l.tar.gzをダウンロードします。

ダウンロードと展開・配置

wget https://go.dev/dl/go1.22.2.linux-arm64.tar.gz
sudo tar -C /usr/local -xzvf go1.22.2.linux-arm64.tar.gz 

PATHの設定

echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc
echo 'export PATH=$HOME/go/bin:$PATH' >> ~/.bashrc

source ~/.bashrc

確認

go version
go version go1.22.2 linux/arm64

MediaMTXのインストール

ラズパイ上でコンパイルします。

git clone https://github.com/bluenviron/mediamtx.git

cd mediamtx
cd internal/protocols/rpicamera/exe
make

makeを実行するとおそらく以下のようにビルドエラーが発生します。

camera.cpp:207:52: error: ‘class libcamera::CameraConfiguration’ has no member named ‘transform’
  207 |         conf->transform = Transform::VFlip * conf->transform;
      |                                                    ^~~~~~~~~
make: *** [Makefile:46: camera.o] Error 1

回避するため、以下の通りcamera.cppを変更します。

camera.cpp L37
using libcamera::Stream;
using libcamera::StreamRole;
using libcamera::StreamConfiguration;
// using libcamera::Transform;         

camera.cpp L202 - 214
    if (params->mode != NULL) {
        StreamConfiguration &raw_stream_conf = conf->at(1);
	raw_stream_conf.size = Size(params->mode->width, params->mode->height);
        raw_stream_conf.pixelFormat = mode_to_pixel_format(params->mode);
        raw_stream_conf.bufferCount = video_stream_conf.bufferCount;
    }

    /*
    conf->transform = Transform::Identity;
    if (params->h_flip) {
        conf->transform = Transform::HFlip * conf->transform;
    }
    if (params->v_flip) {
        conf->transform = Transform::VFlip * conf->transform;
    }

    CameraConfiguration::Status vstatus = conf->validate();
    if (vstatus == CameraConfiguration::Invalid) {
        set_error("StreamConfiguration.validate() failed");
        return false;
    }
    */

    int res = camp->camera->configure(conf.get());
    if (res != 0) {
        set_error("Camera.configure() failed");
        return false;
    }

再度、ビルドします。

$ make
g++ -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result -std=c++17 $(pkg-config --cflags libcamera) -c camera.cpp -o camera.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c encoder.c -o encoder.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c main.c -o main.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c parameters.c -o parameters.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c pipe.c -o pipe.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c sensor_mode.c -o sensor_mode.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c text.c -o text.o
cc -Ofast -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-result $(pkg-config --cflags freetype2) -c window.c -o window.o
g++ base64.o camera.o encoder.o main.o parameters.o pipe.o sensor_mode.o text.o window.o -s -pthread $(pkg-config --libs freetype2) $(pkg-config --libs libcamera) -o exe

通るようになりました。続いて進めます。

cd ../../../../
# ここでリポジトリのルートにいるはずです
go generate ./...
go build -tags rpicamera .

ビルドが完了すると mediamtx が出来上がっているはずです。
続いて、設定ファイルを変更します。ファイル末尾 paths 以降を以下のように記載します。

mediamtx.yml
paths:
  cam:
    source: rpiCamera
    sourceProtocol: automatic

動作確認

起動して動作を確認します。

$ ./mediamtx
2024/05/01 12:34:25 INF MediaMTX v0.0.0
2024/05/01 12:34:25 INF configuration loaded from /home/raspi/gitwork/mediamtx/mediamtx.yml
2024/05/01 12:34:25 INF [path cam] [RPI Camera source] started
2024/05/01 12:34:25 INF [RTSP] listener opened on :8554 (TCP), :8000 (UDP/RTP), :8001 (UDP/RTCP)
2024/05/01 12:34:25 INF [RTMP] listener opened on :1935
2024/05/01 12:34:25 INF [HLS] listener opened on :8888
2024/05/01 12:34:25 INF [WebRTC] listener opened on :8889 (HTTP), :8189 (ICE/UDP)
2024/05/01 12:34:25 INF [SRT] listener opened on :8890 (UDP)
[0:00:44.724271305] [2144]  INFO Camera camera_manager.cpp:284 libcamera v0.2.0+46-075b54d5
[0:00:44.751811083] [2149]  WARN RPiSdn sdn.cpp:39 Using legacy SDN tuning - please consider moving SDN inside rpi.denoise
[0:00:44.754277360] [2149]  INFO RPI vc4.cpp:447 Registered camera /base/soc/i2c0mux/i2c@1/imx708@1a to Unicam device /dev/media1 and ISP device /dev/media3
[0:00:44.755046175] [2144]  INFO Camera camera.cpp:1183 configuring streams: (0) 1920x1080-YUV420
[0:00:44.755459990] [2149]  INFO RPI vc4.cpp:611 Sensor: /base/soc/i2c0mux/i2c@1/imx708@1a - Selected sensor format: 2304x1296-SBGGR10_1X10 - Selected unicam format: 2304x1296-pBAA
2024/05/01 12:34:25 INF [path cam] [RPI Camera source] ready: 1 track (H264)

VLC等RTSPクライアントで以下のURLで確認できます。

rtsp://[hostname]:8554/cam

デーモン化

今回の目的では起動時に立ち上がってほしいのでデーモン化します。

sudo mv mediamtx /usr/local/bin/
sudo mv mediamtx.yml /usr/local/etc/

# systemdファイルの作成
sudo tee /etc/systemd/system/mediamtx.service >/dev/null << EOF
[Unit]
Wants=network.target
[Service]
ExecStart=/usr/local/bin/mediamtx /usr/local/etc/mediamtx.yml
[Install]
WantedBy=multi-user.target
EOF

# サービス登録して起動
sudo systemctl daemon-reload
sudo systemctl enable mediamtx
sudo systemctl start mediamtx
Bitkey Developers

Discussion