Rapberry PI Zero からWebRTCでリアルタイム動画配信
はじめに
raspberry pi zeroは、小型のボードコンピュータですが、ハードウェアエンコーダーを持っています。
これを使うことで、カメラモジュールで取り込んだ動画をハードウェアエンコーダーでH.264へエンコードし、RTP(リアルタイム転送プロトコル)を使って配信することができます。
RTPで配信される動画を見るためには、別途VideoLAN等の動画プレーヤーを用意することになりますが、今回はjanusを使いwebブラウザで参照できるようにすることをゴールとします。
また、今回は画質よりも、なるべく低遅延で配信できるようなパラメタ設定とします。
以下のようなシステムを構築します。

動作テスト( libcamera + ffmpeg )
まずは、raspberry piに接続した、カメラモジュールが正しく動作しているか、動作確認の意味も含めてwebRTCを使わない構成で動作確認を行います。
Raspberry PIのセットアップ
Raspberry PIは、SDカードにRaspberry Pi Imagerで適当なOSイメージを書き込みます。
Raspberry Pi ZeroにはGUIは重たく実用性が低いのと、512MBしかない貴重なメモリを少しでも節約したいので、ここではRaspberry Pi OS Lite(64-bit)を選択しています。
ビュワーのセットアップ
ビュワーとしてはVLCを使います。
カメラモジュールのテスト
カメラモジュールの操作は、libcamera-vidで行います。
Raspberry pi側:
以下のコマンドで、クライアントからの接続を待ちます。
$ libcamera-vid -t 0 --inline --listen -o tcp://0.0.0.0:8888
VLC側:
メニューの「メディア」⇒「ネットワークストリームを開く」から「ネットワークプロトコル」に以下のようなアドレスを指定すると、カメラの画像が表示されます。
tcp/h264://192.168.1.10:8888 # IPアドレスにはRaspberry Piのアドレスを指定
ffmpegのテスト
次に、ffmpegのテストとして、ffmpegに組み込まれているテスト動画をRTPで送信して、VLCで受信してみます。
ffmpegのテスト動画
$ ffmpeg -f lavfi -readrate 1 -i testsrc2=size=768x432:rate=30 \
-c:v h264_v4l2m2m -b:v 1M \
-f rtp rtp://192.168.1.10:8004 # IPアドレスはPCのIPアドレスにします。
VLC側
以下のファイルをメモ帳で作成し、拡張子を.sdpとして保存します。
(IPアドレスはPCのIPアドレスに変更してください)
v=0
o=- 0 0 IN IP4 192.168.1.10
s=FFmpeg RTP Stream
c=IN IP4 192.168.1.10
t=0 0
m=video 8004 RTP/AVP 96
a=rtpmap:96 H264/90000
作成した.sdpファイルをvlcから開くと、以下のようなテスト動画が再生されます。

カメラ画像の配信
libcamera-vidで取り込んだカメラ動画を、パイプ(|)でffmpegに流し込むことでカメラ動画をRTP送信することができるようになります。
Raspberry PI側
$ libcamera-vid --hdr -n -t 0 --inline -o - --level 4.2 \
--width 640 --height 480 \
--denoise cdn_off \
-b 1000K \
--framerate 30 --flush 1 \
| \ # パイプで動画ストリームをffmpegに流す
ffmpeg -i - -c:v copy -b:v 1000K \ # ffmpegでは何もしない
-preset ultrafast -tune zerolatency \
-bufsize 2000K -fps_mode vfr \
-f rtp rtp://192.168.1.10:8004 # IPアドレスはPCのIPアドレスにします。
※libcamera-vidでH.264へのエンコードが行われているため、今回はffmpegでは何もせずそのままrtpストリームに流しています。(-c:v copyの部分)
VLC側
先ほどと同じsdpファイルで受信できます。
v=0
o=- 0 0 IN IP4 192.168.1.10
s=FFmpeg RTP Stream
c=IN IP4 192.168.1.10
t=0 0
m=video 8004 RTP/AVP 96
a=rtpmap:96 H264/90000
.sdpファイルをvlcから開くと、今度はカメラ動画が再生されます。
配信サーバの構築
配信サーバは、webRTCサーバになるjanus-gatewayと、nginxを使います。
それぞれdockerコンテナ上で構築します。
dockerのセットアップ
Docker Desktopをインストールしてください。
janus-gatewayの構築
githubにある手順に従って、コンテナ上に各種ライブラリのインストールしたのち、janus-gatewayのビルドを行います。
以下にDockerfileと、docker-compose.yamlの例を以下に示します。
以下のようなフォルダ構成になります
/
├─ docker-compose.yaml
├─ container/
├─ janus/
├─ Dockerfile
├─ janus-gateway/
│ ├─ :
├─ etc/
├─ janus
├─ janus.jcfg
├─ janus.plugin.streaming.jcfg
├─ janus.transport.http.jcfg
├─ janus.transport.websockets.jcfg
docker関連ファイル
Dockerfile
FROM ubuntu:24.04
RUN apt-get update \
&& apt-get install -y --no-install-recommends tzdata\
&& apt-get install -y git cmake \
&& apt clean
# && apt-get install -y janus \
RUN apt install -y libmicrohttpd-dev libjansson-dev \
libssl-dev libsofia-sip-ua-dev libglib2.0-dev \
libopus-dev libogg-dev libcurl4-openssl-dev liblua5.3-dev \
libconfig-dev pkg-config libtool automake \
meson sudo wget
WORKDIR /work
RUN git clone https://gitlab.freedesktop.org/libnice/libnice \
&& cd libnice \
&& meson --prefix=/usr build && ninja -C build && sudo ninja -C build install \
&& cd ..
RUN wget https://github.com/cisco/libsrtp/archive/v2.2.0.tar.gz \
&& tar xfv v2.2.0.tar.gz \
&& cd libsrtp-2.2.0 \
&& ./configure --prefix=/usr --enable-openssl \
&& make shared_library && sudo make install \
&& cd ..
RUN git clone https://libwebsockets.org/repo/libwebsockets \
&& cd libwebsockets \
&& mkdir build \
&& cd build \
&& cmake -DLWS_MAX_SMP=1 -DLWS_WITHOUT_EXTENSIONS=0 -DCMAKE_INSTALL_PREFIX:PATH=/usr -DCMAKE_C_FLAGS="-fpic" .. \
&& make && sudo make install \
&& cd ../..
COPY containers/janus/janus-gateway /work/janus-gateway
RUN cd janus-gateway \
&& sh autogen.sh \
&& ./configure --prefix=/opt/janus \
&& make && make install && make configs
docker-compose.yaml
services:
janus:
container_name: janus
build:
context: .
dockerfile: containers/janus/Dockerfile
volumes:
- ./containers/janus/etc/janus:/opt/janus/etc/janus
tty: true
command: /opt/janus/bin/janus
ports:
- 8004:8004/udp # ストリーミングの受付PORT
- 8088:8088 # http用
- 8188:8188 # websocket用
janusの設定ファイル
以下の設定ファイルを、containers/janus/etc/janus以下に配置します。
ここでは最低限の設定だけ行っています。
これ以外のオプションについてはドキュメントや、janus-gateway/conf以下にあるサンプルファイルを参照してください。
janus.jcfg
general: {
configs_folder = "/opt/janus/etc/janus"
plugins_folder = "/opt/janus/lib/janus/plugins"
transports_folder = "/opt/janus/lib/janus/transports"
events_folder = "/opt/janus/lib/janus/events"
loggers_folder = "/opt/janus/lib/janus/loggers"
}
janus.plugin.streaming.jcfg
h264-ch10: {
type = "rtp"
id = 10
description = "H.264 live stream ch10"
audio = false
video = true
videoport = 8004
videopt = 126
videocodec = "h264"
videortpmap = "H264/9000"
videofmtp = "profile-level-id=42e01f;packetization-mode=1"
secret = "adminpwd"
}
janus.transport.http.jcfg
general: {
json = "indented"
base_path = "/janus"
http = true
port = 8088
https = false
}
janus.transport.websockets.jcfg
general: {
json = "indented"
ws = true
ws_port = 8188
wss = false
}
構築
最初に、container/janusフォルダに移動して、janus-gatewayをcloneしておきます。
(デモ用のhtmlファイルなどを使いたいので)
$ cd container/janus
$ git clone https://github.com/meetecho/janus-gateway.git
次に、docker-compose.yamlの置かれているディレクトリに移動したのち
以下のコマンドでコンテナのビルドを行います
$ cd ../..
$ docker compose up --build -d
:
$ docker container ls # コンテナが起動していることを確認
:
$ docker logs janus -n 100 # エラーが出ていないことを確認
:
---------------------------------------------------
Starting Meetecho Janus (WebRTC Server) v1.3.3
---------------------------------------------------
:
Loading plugin 'libjanus_streaming.so'...
JANUS Streaming plugin initialized!
:
libwebsockets logging: 0
Websockets server started (port 8188)...
JANUS WebSockets transport plugin initialized!
Loading transport plugin 'libjanus_http.so'...
WebSockets thread started
HTTP transport timer started
HTTP webserver started (port 8088, /janus path listener)...
JANUS REST (HTTP/HTTPS) transport plugin initialized!
起動ログで、
Streaming plugin initialized!
Websockets server started (port 8188)
HHTTP webserver started (port 8088, /janus path listener)
が確認できれば問題なく設定できていると思います。
janusの動作確認は後の章にて行いますので、ここではコンテナが起動していることを確認できればOKです。
nginxのセットアップ
コンテナ用のファイルを以下のように配置します。
/
├─ docker-compose.yaml
├─ container/
├─ janus/
:
├─ nginx/
├─ Dockerfile
├─ conf.d/
├─ default.conf
docker関連ファイル
Dockerfile
FROM nginx:latest
docker-compose.yaml
以下を追加します。
services:
janus:
:
web:
container_name: web
build:
context: .
dockerfile: containers/nginx/Dockerfile
volumes:
- ./containers/janus/janus-gateway/html:/opt/janus/html
- ./containers/nginx/conf.d:/etc/nginx/conf.d
ports:
- 80:80
nginx
nginxの設定ファイルdefault.confを、container/nginx/conf.dに置きます。
default.conf
server {
listen 80;
server_name 0.0.0.0;
location /janus/ {
alias /opt/janus/html/;
}
}
構築
以下のコマンドでコンテナを起動します。
$ docker compose up web --build -d
コンテナが起動したら、
http://localhost/janus/
へアクセスして、以下のデモ画面が表示されることを確認してください。

動作確認
docker container lsコマンドで、jausとwebコンテナが起動していることを確認します。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e30df1b27de8 webrtc-janus "/opt/janus/bin/janus" 27 minutes ago Up 6 minutes 0.0.0.0:8088->8088/tcp, [::]:8088->8088/tcp, 0.0.0.0:8004->8004/udp, [::]:8004->8004/udp, 0.0.0.0:8188->8188/tcp, [::]:8188->8188/tcp janus
6ce3a18c2336 webrtc-web "/docker-entrypoint.…" 45 minutes ago Up 31 minutes 0.0.0.0:80->80/tcp, [::]:80->80/tcp web
動作確認
-
「Demos」⇒「Streaming」を選択して、streaming pluginのデモ画面に移動します。

-
「Start」ボタンを押すと、Stream listに、
janus.plugin.streaming.jcfgで登録した「H.264 live stream ch10(live)」が見えると思いますので、選択して「Watch」ボタンを押します。

-
Raspberry PIから以下のコマンドで動画のライブ配信を開始します。
$ ffmpeg -f lavfi -readrate 1 -i testsrc2=size=768x432:rate=30 \
-c:v h264_v4l2m2m -b:v 1M \
-f rtp rtp://192.168.1.10:8004 # IPアドレスはPCのIPアドレスを指定します。
うまくいけば、ウェブ画面上にて動画の再生が行われます。

Raspberry PIで実行するコマンドを以下のようにすれば、カメラ画像を配信できます。
$ libcamera-vid --hdr -n -t 0 --inline -o - --level 4.2 \
--width 640 --height 480 \
--denoise cdn_off \
-b 1000K \
--framerate 30 --flush 1 \
| \
ffmpeg -i - -c:v copy -b:v 1000K \
-preset ultrafast -tune zerolatency \
-bufsize 2000K -fps_mode vfr \
-f rtp rtp://192.168.1.10:8004 # IPアドレスはPCのIPアドレスにします。
次回
次回は、Rapberry PIとjanusの間に画像認識サーバを入れて、yoloで物体認識をさせてみたいと思います。また、今回はjanusのデモサイトを使って動画を受信しましたが、任意のページに配置する方法についても紹介します。
Discussion