🌟
sora-cpp-sdk-samplesでカメラの映像をローカルに録画しつつWebRTCで送信する
前回の応用
pipe_video_src
を使うと何かのプロセスでI420のビデオデータを生成できればそれをWebRTCで送信できます。
今回はgstreamerでカメラの映像を取り出し2つに分岐させ、片方をエンコードして録画し、もう片方をI420に変換して pipe_video_src
にくわせています。
音声は無しです。
#!/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=30
AUDIO_OPT='--no-audio-device'
RECDIR=$PWD/rec
MAX_FILE_SIZE=$((100 * 1024 * 1024))
MAX_FILES=20
filename="$RECDIR/d%04d.m2ts"
index_wrap=10000
last_index=`ls -t $RECDIR/d[0-9]*.m2ts |head -1 |sed -n -e 's/\.m2ts$//' -e 's/[^0-9]//gp'`
if [ -z $last_index ] ; then
mkdir -p $RECDIR
next_index=0
else
next_index=`echo "($last_index + 1) % $index_wrap" |bc`
fi
touch $RECDIR/start_${next_index}_$(date +%Y%m%d%H%M%S)
FIFO=$PWD/.fifo
rm -f $FIFO
mkfifo $FIFO
./pipe_video_src --log-level 1 $AUDIO_OPT --video-fifo $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 &
gst-launch-1.0 -eq v4l2src device="/dev/video0" ! \
"image/jpeg, width=$WIDTH, height=$HEIGHT, framerate=$FRAMERATE/1" ! \
tee name = t \
t. ! queue2 ! nvv4l2decoder mjpeg=1 ! 'video/x-raw(memory:NVMM)' ! \
nvvidconv ! 'video/x-raw, format=(string)I420' ! \
filesink location=$FIFO blocksize=1048576 \
t. ! queue2 ! nvv4l2decoder mjpeg=1 ! 'video/x-raw(memory:NVMM)' ! \
nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)I420' ! \
nvv4l2h265enc insert-sps-pps=1 iframeinterval=60 bitrate=2000000 ! \
h265parse ! mpegtsmux ! multifilesink location=$filename index=$next_index \
next-file=4 max-file-size=$MAX_FILE_SIZE max-files=$MAX_FILES
gstreamerのところを以下のように書くとmjpegのデコードを2重に行わなくて済むのでよさそうですが、サイズの大きなI420のデータをtee
でコピーすることになるせいか、WebRTCで送信したときの遅延時間が長くなってしまいました。
gst-launch-1.0 -eq v4l2src device="/dev/video0" ! \
"image/jpeg, width=$WIDTH, height=$HEIGHT, framerate=$FRAMERATE/1" ! \
nvv4l2decoder mjpeg=1 ! 'video/x-raw(memory:NVMM)' ! \
nvvidconv ! 'video/x-raw, format=(string)I420' ! \
tee name = t \
t. ! queue2 ! filesink location=$FIFO blocksize=1048576 \
t. ! queue2 ! nvvidconv ! 'video/x-raw(memory:NVMM), format=(string)I420' ! \
nvv4l2h265enc insert-sps-pps=1 iframeinterval=60 bitrate=2000000 ! \
h265parse ! mpegtsmux ! multifilesink location=$filename index=$next_index \
next-file=4 max-file-size=$MAX_FILE_SIZE max-files=$MAX_FILES
関連
Discussion