[Kinesis Video Streams] capsfilerとvideoscaleを使って、好みの解像度で動画を送信してみました

2020.02.21

1 はじめに

CX事業本部の平内(SIN)です。

Kinesis Video Streamsへ送信する動画は、その用途によって、適切な解像度があると思います。また、通信帯域や、保存されるデータのサイズにも解像度は影響すると思います。(動画は、h264若しくは、h265でエンコードされているため、解像度が比例的に影響するわけではありません)

今回は、Webカメラで撮影した動画を、Raspberry Piで送信する場面で、解像度を色々と設定してみました。

2 カメラの対応解像度

使用するカメラの性能によって、取り出せる解像度が決まっています。

使用しているカメラの対応する形式や解像度は、gst-device-monitor-1.0で確認出来ます。今回、確認作業に使用したWebカメラ(LogicoolC 920)の出力は、以下のようになっています。

$ gst-device-monitor-1.0
Probing devices...


Device found:

    name  : HD Pro Webcam C920
    class : Video/Source
    caps  : video/x-raw, format=(string)YUY2, width=(int)2304, height=(int)1536, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)2/1;
            video/x-raw, format=(string)YUY2, width=(int)2304, height=(int)1296, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)2/1;
            video/x-raw, format=(string)YUY2, width=(int)1920, height=(int)1080, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)5/1;
            video/x-raw, format=(string)YUY2, width=(int)1600, height=(int)896, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)1280, height=(int)720, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)960, height=(int)720, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)1024, height=(int)576, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)800, height=(int)600, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)864, height=(int)480, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)800, height=(int)448, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)640, height=(int)360, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)432, height=(int)240, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)352, height=(int)288, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)320, height=(int)240, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)320, height=(int)180, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)176, height=(int)144, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)160, height=(int)120, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };
            video/x-raw, format=(string)YUY2, width=(int)160, height=(int)90, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction){ 30/1, 24/1, 20/1, 15/1, 10/1, 15/2, 5/1 };

(略)
    gst-launch-1.0 v4l2src ! ...

3 capsfiler

capsfilterで、取り出したい解像度を指定する事ができます。下記は、640✕480を取り出している様子です。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! capsfilter caps=video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

なお、capsfilter caps= の記述は、通常省略されます。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

(1) 低画質で送信してみる

下記は、160✕90という低解像度を指定しています。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=160,height=90,framerate=30/1 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

※ 低い解像度で、一部の色が変わってしまっているのは、原因不明です。

(2) 高画質で送信してみる

反対に、1600✕896という高い解像度を指定しています。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=1600,height=896,framerate=15/2 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

4 videoscale

先の、gst-device-monitor-1.0 の出力から、Widthが640の解像度は、以下の2種類です。

width=640, height=480
width=640, height=360

ここで、下記のように、未対応の解像度(640✕400)を指定すると、Internal data stream error. となってしまいます。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=400,framerate=30/1 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

(略)

ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.

しかし、videoscaleを通すことで、解像度の変更は可能です。 下記では、120✕90に変換しています。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! videoscale ! video/x-raw,width=120,height=90 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

なお、解像度の変換では、縦横の比率に注意が必要です。 下記は、元の解像度が640✕480でなく640✕360のものを、上記と同じ用に、120✕90に変換した例です。

$ gst-launch-1.0 -v v4l2src ! videoconvert ! video/x-raw,format=I420,width=640,height=360,framerate=30/1 ! videoscale ! video/x-raw,width=120,height=90 ! omxh264enc periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=test-stream

縦横の比率がおかしくなっている事が分かります。

5 最後に

今回は、ニーズに応じて解像度を変更できるように、その要領を確認してみました。

なお、capsfilerは、単なるフィルタですが、videoscaleの方は、変換を行っていますので、送信するPCに負荷がかかります。可能であれば、カメラの対応する解像度から選択するのが良いかも知れません。