[Kinesis Video Streams] Mac上で各種ソースからの動画のアップロード 〜 kvssinkを利用する場合のGStreamerの使用方法

2019.12.31

1 はじめに

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

Kinesis Video Streamsでは、プロデューサーの一つとして、標準的なストリーミング管理ライブラリであるGStreamerのプラグインとして利用可能なシンクエンメント(kvssink)が提供されています。
参考:例: Kinesis ビデオストリーム プロデューサー SDK GStreamer プラグイン

GStreamerでは、gst-launch-1.0を使用して、コマンドラインから軽易に下記のような構成を実現することが可能になります。

各種リソース ->  フィルタ、変換など -> kvssink -> Kinesis Video Streasms

今回は、MacOS上で、kvssinkを利用する方法を色々試してみた記録です。

2 kvssinkについて

最初に、kvssinkについて確認しました。

Gstreamerに含まれる、gst-inspect-1.0というツールを利用すると、エレメントの詳細情報を見ることができます。

$ gst-inspect-1.0 kvssink

上記コマンドでは、エレメントの入口(SINK)と、出口(SRC)が表示されますが、kvssinkは、シンクとして実装されているため、SRCは無く、SINKは、下記のとおりとなっています。

ここから、Videoにつては、x-h264及び、x-h265に対応していることが分かります。なお、ビデオのフォーマットは、avcのみです。

SINK template: 'audio_%u'
    Availability: On request
    Capabilities:
      audio/mpeg
            mpegversion: { (int)2, (int)4 }
          stream-format: raw
               channels: [ 1, 2147483647 ]
                   rate: [ 1, 2147483647 ]

  SINK template: 'video_%u'
    Availability: On request
    Capabilities:
      video/x-h264
          stream-format: avc
              alignment: au
                  width: [ 16, 2147483647 ]
                 height: [ 16, 2147483647 ]
      video/x-h265
              alignment: au
                  width: [ 16, 2147483647 ]
                 height: [ 16, 2147483647 ]

同コマンドでは、エレメントに指定できるパラメータも確認できます。パラメータのいくつかを以下に、列挙させて頂きます。

  • stream-name: ストリーム名 Default: "DEFAULT_STREAM"
  • access-key: AWS アクセスキー
  • secret-key: AWS シークレットキー
  • aws-region: AWS リージョン Default: "us-west-2"
  • retention-period: ストリームの保存期間(単位:時間) Default: 2
  • streaming-type: タイプ Default: realtime
    • 0: realtime - streaming type realtime
    • 1: near-realtime - streaming type near realtime
    • 2: offline - streaming type offline
  • content-type: コンテンツタイプ Default: null
  • max-latency: 最大遅延(単位:秒) Default: 60
  • fragment-duration: フラグメント遅延(単位:ミリ秒)Default: 2000
  • timecode-scale: Timecode Scale.(単位:ミリ秒)Default: 1
  • key-frame-fragmentation: trueの場合、各キーフレームで新しいフラグメントを生成します。それ以外の場合、fragment-durationが経過した後、最初のキーフレームで新しいフラグメントを生成する Default: true

3 Mac上での入力ソース

続いてMac上で、いくつかの動画リソースについて確認してみます。

ここでは、いきなりkvssinkに出力すると、その確認が、やや複雑になるため、画面で動画を確認するだけとし、出力先にautovideosinkを利用します。

(1) テスト入力

テストパターンの入力元となるvideotestsrcを入力として、autovideosink に出力する場合は下記のようになります。静止画にも見えますが、右下の砂嵐を見ると動画であることを感じられます。

$ gst-launch-1.0 videotestsrc ! autovideosink

(2) 本体のカメラ

続いて、Mac本体のカメラを入力とします。

$ gst-launch-1.0 autovideosrc ! videoconvert ! video/x-raw ! autovideosink

autovideosrcは、デフォルトのビデオソースからの入力ですが、avfvideosrc「Video Source (AVFoundation)」にデバイスIDを指定しても利用可能です。

$ gst-launch-1.0 avfvideosrc device-index=0 ! videoconvert ! video/x-raw ! autovideosink

videoconvertを挟んでいるのは、Macのカメラの解像度が、そのままでは、autovideosinkで認識できず、緑一色の画面になってしまうためです。

(3) USB接続のWebカメラ

avfvideosrcで認識できているため、デバイスIDを指定して利用可能です。デバイスのインデックス(番号)は、カメラの接続数、接続順などによって変化します。

$ gst-launch-1.0 avfvideosrc device-index=1 ! videoconvert ! video/x-raw ! autovideosink

(4) RTSPサーバ

RTPSサーバからの入力は、rtspsrcエレメントで受けることができます。RTPSサーバでは、H264へのエンコードが終わっているので、decodebinで逆に戻しています。

$ gst-launch-1.0 rtspsrc location=rtsp://192.168.0.113 ! decodebin !  autovideosink

※RTSPサーバは、Live-Reporter - 監視カメラ https://apps.apple.com/jp/app/live-reporter-監視カメラ/id996017825をiPhoneにインストールして利用させて頂きました。

3 kvssinkでの送信

kvssinkは、最初に確認したとおり、h264で、stream-format=avc,alignment=auな入力を要求するため、シンクに送る前に、以下のように、h264parseで、パースします。

h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name="STREAM_NAME" access-key="xxxxxxx" secret-key="xxxxxxx"  aws-region="ap-northeast-1"

また、入力が、h264にエンコードされていない場合、Macで利用可能なエンコーダーであるvtenc_h264_hwを使用します。

vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512

上記を参考に、入力を、kinesis Video Streamsに送る場合のコマンドラインは、以下のようになりました。

(1) テスト入力

$ gst-launch-1.0 videotestsrc ! videoconvert ! video/x-raw,format=I420,width=960,height=720 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

(2) 本体のカメラ

$ gst-launch-1.0 autovideosrc ! videoconvert ! video/x-raw,format=I420,width=1280,height=720 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

(3) USB接続のWebカメラ

本体カメラを使用する場合と、ほぼ同じです。画面のサイズだけを合せました。

$ gst-launch-1.0 avfvideosrc device-index=1 ! videoconvert ! video/x-raw,format=I420,width=960,height=720 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

実は、USB接続のWebカメラについては、上記では、やや安定しませんでした。後述しますが、フレームレートを下げ(要領については後述)てみると安定したので紹介させて頂きます。

$ gst-launch-1.0 avfvideosrc device-index=1 ! videorate ! video/x-raw,framerate=15/1 ! videoconvert ! video/x-raw ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

(4) RTSPサーバ

ここでは、RTSPサーバでh264にエンコードされたデータをrtph264depayでそのまま使用しています。

$ gst-launch-1.0 rtspsrc location=rtsp://192.168.0.113 short-header=TRUE ! rtph264depay ! video/x-h264, format=avc,alignment=au ! h264parse ! kvssink stream-name="sampleStream" storage-size=128 access-key="XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

4 変換

ここからは、個人的に、あったら便利だなと思った変換についてです。

(1) フレームレート変換

上記のUSB接続のWebカメラで既に使用しましたが、videorateでフレーム数を変更できます。

下記は、USB接続のWebカメラの映像をフレームレート1/15で送信しているものです。

$ gst-launch-1.0 avfvideosrc device-index=1 ! videorate ! video/x-raw,framerate=15/1 ! videoconvert ! video/x-raw ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

(2) 解像度変換

videoscaleで解像度の変更が可能です。下記は、本体のカメラから640✕360でKVSに送っています。

gst-launch-1.0 autovideosrc ! videoscale ! video/x-raw, width=640, height=360 ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key=XXXXX" secret-key="XXXXX" aws-region="ap-northeast-1"

(3) 反転

videoflipで画像の反転が可能です。カメラを使用する向きによっては、反転したくなるニーズがあると思います。

下記では、videoflip method=horizontal-flipで垂直軸を中心に反転を行っています。

gst-launch-1.0 autovideosrc ! videoflip method=horizontal-flip ! videoconvert ! video/x-raw ! vtenc_h264_hw allow-frame-reordering=FALSE realtime=TRUE max-keyframe-interval=45 bitrate=512 ! h264parse ! video/x-h264,stream-format=avc,alignment=au,profile=baseline ! kvssink stream-name=sampleStream storage-size=512 access-key="XXXXX" secret-key="XXXXXX" aws-region="ap-northeast-1"

反転したものと、していないものの比較です。

5 最後に

色々知識不足で、個人的には、GStreamerの各種エレメントを使いこなすのは、非常にハードルの高いものに感じています。とりあえずは、Kinesis Video Streamsのプロデューサーとして使用できるようにと色々試行錯誤しましたが、まだまだ、分かっていないと感じています。みなさん、是非、教えて(突っ込んで)やって下さい。

感想です・・・今回、試した中では、RTSPサーバからの入力が最も安定していました。今更ですが、H264で出力できるカメラなど、外部でH264のエンコードを行うのが、KVSへの安定した送信に繋がると感じました。(すいません、当たり前ですね・・・)