🐥

sora-cpp-sdk-samplesでカメラの代わりにpipe経由でビデオデータを入力してWebRTCで送信してみた

2022/07/03に公開

前回の続き。
https://zenn.dev/tetsu_koba/articles/06e11dd4870796

ビデオの入力をカメラからではなく、別のプロセスで生成したI420形式のビデオデータをpipe経由で取り込んでWebRTCで送信するようにしてみました。

https://github.com/tetsu-koba/sora-cpp-sdk-samples/tree/pipe_video_src

PipeVideoCaptureのclassはsora-cpp-sdkのV4L2VideoCaptureの構造を参考にしました。特にスレッドを使うところはそっくり真似ています。
ポイントはI420のビデオデータをlibwebrtcに渡す部分です。

void PipeVideoCapturer::OnCaptured(uint8_t* data) {
  auto w = _width;
  auto h = _height;
  auto i420_buffer = webrtc::I420Buffer::Copy(w, h,
					      data, w,
					      data + (w * h), w/2,
					      data + (w * h) + (w/2 * h/2), w/2);
  webrtc::VideoFrame video_frame = webrtc::VideoFrame::Builder()
    .set_video_frame_buffer(i420_buffer)
    .set_timestamp_rtp(0)
    .set_timestamp_ms(rtc::TimeMillis())
    .set_timestamp_us(rtc::TimeMicros())
    .set_rotation(webrtc::kVideoRotation_0)
    .build();
  OnCapturedFrame(video_frame);
}

自分で描画した映像を送信するときの参考になると思います。
I420のデータはかなりサイズが大きいので、解像度フレームレートを高くする場合にはプロセス間でのデータの受け渡し方法に工夫が必要だと思います。例えば、共有メモリ上に数フレーム分をリングバッファとして持つとか。

使い方

--video-fifo オプションで入力するfifo(名前付きパイプ)を指定します。- を指定すると標準入力になります。そのパイプに別のプロセスからI420のビデオデータを流し込みます。

ffmpegでテストパターンを作ってそれを送信する方法。

#!/bin/sh -eux

SIGNALING_URL=wss://207-148-110-182.canary.sora.sora-labo.shiguredo.app/signaling
CHANNEL_ID=tetsu-koba@sora-devtools
SIGNALING_KEY=xxxyyy
WIDTH=1280
HEIGHT=720
FRAMERATE=10
AUDIO_OPT='--no-audio-device'

ffmpeg -re -f lavfi -i testsrc=s=${WIDTH}x${HEIGHT}:r=$FRAMERATE -pix_fmt yuv420p -f rawvideo pipe: | \
./pipe_video_src --log-level 1 $AUDIO_OPT --video-fifo - --resolution ${WIDTH}x${HEIGHT} --framerate $FRAMERATE \
    --signaling-url $SIGNALING_URL --channel-id $CHANNEL_ID \
    --multistream true --video-codec-type H264 \
    --metadata "{\"signaling_key\": \"$SIGNALING_KEY\"}" > log 2>&1

Discussion