🥐

Amazon Kinesis Video Streams にUbuntu上のUSBカメラから動画配信するコンテナを作りました

2023/09/11に公開

この記事の最後に、作成したdockerfileとcompose.yamlを貼ります。経緯とかに興味ない人は飛んでください

作った経緯

Amazon Kinesis Video Streamsに動画を配信したいという要件があり、使い方を調べてみました。
https://aws.amazon.com/jp/kinesis/video-streams/features/?nc=sn&loc=2

Amazon Kinesis Video Streams は、接続されたデバイス上で構築、設定できる C++ および Java の SDK を提供します。

C++とかJavaとか普段使わないのでつらい

SDK は GStreamer プラグインとしても利用可能で、カスタムメディアデータフローの構築ができます。

GStreamerというやつを使えば、C++とかJavaを使わなくても配信できるらしい

SDK はソースから構築するか、または Ubuntu、MacOS、Raspberry Pi デバイスで使える Docker イメージを用いて簡単な Docker プルでデプロイでき、わずか数分でストリーミングビデオを開始できます。

ソースから構築はツラいので、Dockerイメージを使おう

AWS提供のDockerイメージで、ネットワークカメラの動画を配信してみた

C++やJAVAは知見がないしプラグインをソースから構築するのが面倒くさそうなので、AWS提供のDockerイメージを使ってネットワークカメラの動画を配信してみました。

Dockerイメージの使い方がこちら
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/examples-gstreamer-plugin.html#examples-gstreamer-plugin-docker

Dockerイメージ内から配信するコマンドのこちら
https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/examples-gstreamer-plugin.html#examples-gstreamer-plugin-launch

いやー、、、ドキュメント分かりにくいし、Dockerイメージ使うにしては面倒くさくないか?

面倒くさいので、compose.yamlを作った

compose.yaml
# dockerイメージをダウンロードする際は、事前に下記コマンドでecrにloginしてください。
# $ aws ecr get-login-password --region us-west-2 | docker login -u AWS --password-stdin https://546150905175.dkr.ecr.us-west-2.amazonaws.com
services:
  gstreamer:
    image: 546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-amazon-linux
    network_mode: host
    env_file: .env
    command: /bin/bash -c "./kvs_gstreamer_sample ${VIDEO_STREAM_NAME} ${RTSP_URL}"
.env
AWS_DEFAULT_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=(AWSのアクセスキー)
AWS_SECRET_ACCESS_KEY=(AWSのシークレットアクセスキー)
VIDEO_STREAM_NAME=(Kinesis Video Streamのリソース名)
RTSP_URL=(ネットワークカメラのURL)

配信出来でました。(画質が低いわけではなく、プライバシー保護のためモザイクをかけております)

いやいやいや、10秒以上の遅延って遅くない?

ググって調べた感じ普通にそのくらい遅延するみたいではあるのですが、やっぱり遅いなぁと。WebRTCを使えば早くなるだろうけど、AWS上に一定期間動画を保存しておきたかったので却下。
それで思ったことが、

  • ネットワークカメラだと カメラ->PC->AWS の経路でネットワークを2回通るから遅くなるのでは?
  • USBカメラなら遅延が減るのでは?

USBカメラ試してみた

ということで、ネットワークカメラからの動画配信は遅延が大きかったので、USBカメラの動画をAWS提供のDockerイメージを使って配信しようとしました。
ですが、母艦がMacやWindowsの場合はコンテナ内からカメラを認識できないという問題があります。母艦からコンテナ内に動画を送りつける方法は無くはないですが、それは結局遅延するので却下。

・・・・・・

仕方がないのでUbuntuのPCを用意しました。母艦がLinuxならコンテナ内からでもカメラが使えますので、AWS提供のUbuntu向けDockerイメージを使って配信しようとしました。
その結果、、、

glib.GError: no element "x264enc"

動画のエンコードでエラーになりました。

gst-inspect x264enc

No such element or plugin 'x264enc'

AWS提供のコンテナ、エンコーダーが認識されてないじゃん。。。PATHが通ってないんじゃないかとか、手動でインストールしたら動くんじゃないかとかイロイロ試したのですが、結局動かずでした。前述のネットワークカメラの場合はカメラ側で動画エンコードをしていたのでこの問題は発生しませんでした。
(Ubuntu向けのDockerイメージがAmazon Linuxベースで作られているのがよくないのでは?)

USBカメラは動画エンコードができる高級品ではないのでアプリ側でエンコードしてから配信する必要があります。でも、AWSが用意したDockerイメージを使うとエンコーダーが動かない。。。もういいや。。。公式に頼らず自力でビルドしてContainerイメージを作ろう。。。
と判断して作ったものが以下です。

作ったもの

dockerfile
FROM ubuntu:22.04 AS base

# ビルドと実行の両方に共通するライブラリをインストール
RUN apt-get update && \
  apt-get install -y \
  libgstreamer-plugins-base1.0-dev


FROM base AS build

WORKDIR /kinesis_video

# ビルドに必要なものをインストール
RUN apt-get update && \
  apt-get install -y \
  cmake m4 git build-essential \
  default-jdk

# ソースコードをclone
RUN git clone https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp.git

# ビルド
RUN mkdir ./amazon-kinesis-video-streams-producer-sdk-cpp/build
RUN cd ./amazon-kinesis-video-streams-producer-sdk-cpp/build && \
  cmake .. -DBUILD_GSTREAMER_PLUGIN=ON -DBUILD_JNI=TRUE && \
  make


FROM base AS runtime
WORKDIR /kinesis_video

# ビルドしたものをコピー(buildとlibだけだとエラーになったので、全部持ってくる)
COPY --from=build /kinesis_video/amazon-kinesis-video-streams-producer-sdk-cpp /kinesis_video/amazon-kinesis-video-streams-producer-sdk-cpp

# ライブラリのパスを通す
ENV LD_LIBRARY_PATH=/kinesis_video/amazon-kinesis-video-streams-producer-sdk-cpp/open-source/local/lib
ENV GST_PLUGIN_PATH=/kinesis_video/amazon-kinesis-video-streams-producer-sdk-cpp/build

# 必要なgstreamerのプラグインをインストール
RUN apt-get update && \
  apt-get install -y \
  gstreamer1.0-plugins-base-apps \
  gstreamer1.0-plugins-good \
  gstreamer1.0-plugins-ugly \
  gstreamer1.0-plugins-bad

# 何故かsslエラーになるので再インストールする
RUN apt-get reinstall -y ca-certificates && \
  update-ca-certificates
compose.yaml
services:
  kinesis-video-stream:
    build: .
    env_file: .env
    devices:
      - "/dev/video0:/dev/video0"
    command: /bin/bash -c 'gst-launch-1.0 -v v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! x264enc  bframes=0 key-int-max=45 bitrate=500 tune=zerolatency ! video/x-h264,stream-format=avc,alignment=au ! kvssink stream-name=${VIDEO_STREAM_NAME} storage-size=128 access-key=${AWS_ACCESS_KEY_ID} secret-key=${AWS_SECRET_ACCESS_KEY}'
.env
AWS_DEFAULT_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=(AWSのアクセスキー)
AWS_SECRET_ACCESS_KEY=(AWSのシークレットアクセスキー)
VIDEO_STREAM_NAME=(Kinesis Video Streamのリソース名)

使い方

  1. .envを自分の環境にあわせて編集する
  2. docker compose up

動作確認

AWSコンソール上から配信された動画を確認できます(画質が低いわけではなく、プライバシー保護のためモザイクをかけております)

AWS公式提供のDockerイメージでは配信出来ませんでしたが、自力で構築したイメージからは無事に配信できました。
遅延もネットワークカメラと比べてかなり少ないです!

以上です!!

NCDCエンジニアブログ

Discussion