Jetson Nanoに取り付けたカメラC920をGStreamerを使って映像と音声をRTSPで配信する

# はじめに

本記事はJetson Nanoに取り付けたカメラC920を使って映像と音声をRTSPで配信する試みである。

この記事の前に「[Jetson Nanoでストリーミング配信を行う](https://qiita.com/yamamo-to/items/1a157561cbae665f05ae)」でC920の映像をMotion JPEGで配信する試みを行った。うまく動作したかに見えたが、悲しいことにiPhoneのブラウザではMotion JPEGを再生することができなかった。さらにはiPhoneにインストールしたVLCでもこのMotion JPEGは見えなかった。

仕方がないのでGStreamerを使ってiPhoneでも閲覧可能な配信を行うことにした。またC920はカメラの両サイドにマイクがついており映像と音声の両方が取得できるので、これを同じネットワーク内に接続された別の端末から受信したいと思う。

# 環境

| マシン | 役割 | 内容 |
|---|---|---|
| Jetson Nano | サーバ | 接続されたカメラ(C920)の映像・音声を配信 |
| MacBook Air | クライアント | VLCを使ってサーバの映像・音声を受信 |
| iPhone | クライアント | VLC Appを使ってサーバの映像・音声を受信 |

# 事前準備

カメラの状態を確認するために`v4l2-ctl`コマンドを使うため次のように`v4l-utils`パッケージをインストールしておく。

```bash:JetsonNano上で実行
sudo apt install v4l-utils
```

また恒例となりつつあるRTSPで配信するためのtest-launchというプログラムを使用する。下記からダウンロードしてコンパイルする必要がある。
https://github.com/GStreamer/gst-rtsp-server/blob/master/examples/test-launch.c

```bash:ターミナル
sudo apt install libgstrtspserver-1.0-dev
gcc -o test-launch test-launch.c `pkg-config --cflags --libs gstreamer-rtsp-server-1.0`
```

# C920について

## 対応フォーマット

C920は3種類のフォーマット(YUYV, H264, MJPG)に対応している。

```bash:ターミナル
$ v4l2-ctl -d /dev/video0 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'YUYV'
        Name        : YUYV 4:2:2

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'H264' (compressed)
        Name        : H.264

        Index       : 2
        Type        : Video Capture
        Pixel Format: 'MJPG' (compressed)
        Name        : Motion-JPEG
```

H264やMJPGと聞くと、あぁ動画で良く聞くアレか、と考えたが同時に「え！？C920ってH264で出せるの?」などと知ったのはつい先日の出来事である。

## 壮大なる勘違い

カメラとマイクがセットでついているので、漠然と「映像と音声の両方が含まれたコンテナ」がカメラの出力として渡されるものだと考えていた。すなわち下記のような設計になるものだと考えていた。
![c920_bad_concept.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/07317ce0-92c8-26e4-2835-17926a44428f.png)

残念ながらこのイメージは間違っていて、正しくは下のようなイメージである。
![c920_correct_concept.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/f89d8581-2b1a-9e87-9912-30b3fb52d5fc.png)
カメラはカメラ、マイクはマイクとして、それぞれ設定することになる。

# GStreamerの設定

## カメラ編

自分の環境ではJetson NanoにUSBで取り付けたC920だけがある。他にカメラはないため`/dev/video0`にカメラがある。

```bash:ターミナル
$ v4l2-ctl --list-devices
HD Pro Webcam C920 (usb-70090000.xusb-2.4):
	/dev/video0
```

GStreamerのパイプラインでは、C920はH264で出力できるためRTSPのH264にそのまま渡せば良い。

```
v4l2src device=/dev/video0 ! video/x-h264,width=640,height=480,framerate=30/1 ! rtph264pay name=pay0 pt=96
```

## マイク編

`pactl list`コマンドで利用可能なマイクの一覧が表示される。長いので`alsa_input`だけを抽出する。

```bash:ターミナル
$ pactl list | grep alsa_input
	Name: alsa_input.platform-sound.analog-stereo
	Name: alsa_input.usb-046d_HD_Pro_Webcam_C920_87B53EDF-02.iec958-stereo
```

2つ目の長い文字列がC920のマイクのデバイス名である。これを使ってGStreamerのパイプラインを記述すると以下のようになる。

```
pulsesrc device=alsa_input.usb-046d_HD_Pro_Webcam_C920_87B53EDF-02.iec958-stereo ! audioconvert ! vorbisenc ! rtpvorbispay name=pay1 pt=97
```

特に意味はないが音声のコーデックにはVorbisを使った。

# RTSPでの配信

あとは上の2つをマージするだけである。長いのでスクリプトにした。

スクリプト中の`video_device`や`audio_device`は同じC920であっても環境ごとに異なるため、環境にあったデバイス名に置き換える必要がある。

```shell:C920toRTSP.sh
#!/bin/bash

video_device=/dev/video0
audio_device=alsa_input.usb-046d_HD_Pro_Webcam_C920_87B53EDF-02.iec958-stereo

video=(
    "v4l2src device=$video_device"
    "video/x-h264,width=640,height=480,framerate=30/1"
    "rtph264pay name=pay0 pt=96"
)

audio=(
    "pulsesrc device=$audio_device"
    "audioconvert"
    "vorbisenc"
    "rtpvorbispay name=pay1 pt=97"
)

pipeline_video="$(IFS=!; echo "${video[*]}" | sed 's/!/ ! /g')"
pipeline_audio="$(IFS=!; echo "${audio[*]}" | sed 's/!/ ! /g')"

pipeline="$pipeline_video $pipeline_audio"

echo "$pipeline"
./test-launch "$pipeline"
```

# VLCでの受信

VLCを使ってのアクセスは下記のURLを開く。MacBook AirもiPhoneも同じである。

rtsp://IPアドレス:8554/test

RTSPで配信すると複数のクライアントで同時に受信が可能となる。iPhoneのVLC Appで受信しているところをカメラで撮像したのが下記である。

![iphone_vlc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252224/63cc4e47-4526-aa91-c5d2-457a82c299fc.png)

iPhoneでも動画が受信できているのが分かる。音も出ている！

# まとめ

Jetson Nanoに取り付けたカメラ`C920`を使って、映像と音声の両方をRTSPにより配信することが可能となり、iPhoneのVLCを使って閲覧することが可能となった。