ffmpegでラップトップのWebカメラをリモートで使う

先日、Periscope というストリーム配信サービスを使って、Vim Vixen のライブコーディングをしてみました。 配信用の Web カメラがほしかったのですが、あいにく自分は Web カメラを持っていません。 そこで MacBook に内蔵されている Web カメラを、遠隔の Web カメラとして利用できたのでその設定メモです。

全体の構成

以下の構成で配信をしました。 作業用のデスクトップマシン (Linux) は、配信用のマシンも兼ねています。 MacBook からはネットワーク経由でデスクトップマシンに映像を届けます。 デスクトップマシン上では OBS (Open Broadcaster Software) を使って、作業風景と Web カメラの映像を合成して、Periscope に配信します。

配信の構成図

MacBook 上の Web カメラの映像は同じネットワーク内にあります。 MacBook のカメラの映像は、MPEG transport stream という配信用の動画形式でデスクトップマシンに映像を送ります。 ffmpeg を使うことで、Web カメラの映像を MPEG transport stream として任意の IP アドレスとポートに UDP 形式で送信できます。 Mac OS ではHomebrewから ffmpeg をインストールできます。

OBS では MPEG transport stream の映像を入力ソースとして扱えません。 そこでデスクトップ上で、MPEG transport stream の映像を仮想ビデオデバイス (v4l2loopback) に流します。 すると OBS 上からは、あたかも Web カメラのように入力ソースとして選択できます。

Web カメラ用のラップトップの準備

上記の構成は MacBook で配信しましたが、Linux のラップトップでも動作確認ができたので、両方の手順を残します。

MacBook の場合

まず利用するビデオデバイスを探します。 Mac OS 上上で以下のコマンドで利用可能なビデオデバイス一覧は ffmpeg コマンドで取得できます。

$ ffmpeg -f avfoundation -list_devices true -i ""
ffmpeg version 4.2.1 Copyright (c) 2000-2019 the FFmpeg developers
...
[AVFoundation input device @ 0x7ff8ee904340] AVFoundation video devices:
[AVFoundation input device @ 0x7ff8ee904340] [0] FaceTime HD Camera (Built-in)
[AVFoundation input device @ 0x7ff8ee904340] [1] Capture screen 0
...

MacBook の場合は "FaceTime xxxxxx" というデバイスが、搭載されている Web カメラの名前です。 ffmpeg コマンドでカメラの映像を、MPEG transport stream 形式でデスクトップに対して配信します。 ここでは配信用のマシンの IP アドレスが 192.168.1.100 だとします。

$ ffmpeg \
    -framerate 30.000030 \  # カメラのフレームレート
    -f avfoundation \       # Appleの動画配信用の形式
    -pix_fmt uyvy422 \      # カメラのピクセルフォーマット
    -i "FaceTime HD Camera (Built-in)" \  # デバイス名
    -vcodec libx264 \     # ビデオコーデックにx264を使う
    -preset ultrafast \   # 低遅延用なプリセット
    -tune zerolatency \   # 低遅延用のチューニング
    -f mpegts \           # MPEG transport stream
    udp://192.168.1.100:12000?pkt_size=1316 # 送信先のアドレス、ポートとパケットサイズ

次に配信用マシン上で、Web カメラの映像が送られているかをチェックします。 MPEG transport stream の映像をチェックするには ffplay コマンドを使います。

$ ffplay -fflags nobuffer udp://192.168.1.100:12000

Linux ラップトップの場合

Linux ラップトップでもほぼ同じ手順です。 Linux の場合は、Web カメラのデバイスには /dev/video* というデバイスファイルからアクセスします。 v4l2-ctl コマンドでデバイスの詳細を確認できるので、Web カメラ用のデバイスを特定できます。

$ v4l2-ctl --device /dev/video0 --info

デバイスの名前がわかれば、先程と同じように ffmpeg で配信用マシンに MPEG transport stream で映像を流します。

$ ffmpeg \
    -i /dev/video0 \
    -vcodec libx264 \
    -preset ultrafast \
    -tune zerolatency \
    -f mpegts \
    udp://192.168.1.100:12001?pkg_size=1316

確認も、配信用マシン上で ffplay コマンドを使います。

$ ffplay -fflags nobuffer udp://192.168.1.100:12001

v4l2loopback に接続

以上で、配信用マシンに映像が届きました。 次に届いた映像を OBS の入力ソースとして扱えるように、仮想ビデオデバイスに映像を流します。

Linux では v4l2loopback というドライバを使うと、いろいろな映像をビデオデバイスとして扱えます。 たとえば OBS だけでなく、Zoom やブラウザからも Web カメラとしてアクセスできます。 v4l2loopback は以下のレポジトリからインストールできます。

インストールが完了すると modprobe でモジュールをロードします。

$ sudo modprobe v4l2loopback            # 1つの仮想デバイスを作成
$ sudo modprobe v4l2loopback devices=4  # 複数の仮想デバイスを作成

そして配信用マシン上で ffmpeg コマンドを実行して、MPEG transport stream の映像を v4l2loopback に流します。

$ ffmpeg \
    -loglevel fatal \   # ログレベル
    -fflags nobuffer \  # バッファしない
    -i udp://192.168.1.6:12000 \  # 配信機材自身のアドレス、ポート
    -f v4l2          # Linuxのビデオドライバの形式
    -pix_fmt yuv420p # ピクセルフォーマット
    /dev/video0      # 出力先デバイス (v4l2loopback)

これで OBS から Video Capture Device (V4L2) を選択すると、作成した仮想デバイスを選択できるようになっています。 以上の手順で、MacBook の Web カメラの映像が、OBS にも流れるようになりました。

まとめ

以上の配信環境では、Web カメラの体感的な遅延は 0.5 秒程度でした。 この機会に OBS も触ってみましたが、お手軽で便利ですね。 元々自分は配信はしたことがありませんでしたが、配信環境を揃えたいという機運が高まってきています。 しばらく配信環境の探求が続きそうです。


Profile picture

Shin'ya Ueoka

B2B向けSaaSを提供する会社の、元Webエンジニア。今はエンジニアリング組織のマネジメントをしている。