[Kinesis Video Streams] capsfilerとvideoscaleを使って、好みの解像度で動画を送信してみました
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に負荷がかかります。可能であれば、カメラの対応する解像度から選択するのが良いかも知れません。