a minute ago

ラズパイ, Jetsonに接続したカメラ映像をAWS Kinesis Video Streamsで配信


ラズパイにUSBで刺したwebカメラの映像をKinesis Video Streamsで配信する方法を解説。

試したのはラズパイだが、おそらくJetsonでも動く。

AWS側の設定

ビデオストリーム作成

Management Console > Kinesis Video Streams > ビデオストリームを作成押下。ビデオストリームを作成する。ビデオストリーム名は後で使うのでメモ。

IAM作成

IAM > ユーザーを追加を押下。適当に埋めて行く。

アクセスの種類はプログラムによるアクセスを選択

アクセス許可の設定 > 既存のポリシーを直接アタッチから以下を追加しておく。後でラズパイ側の設定をするときにdockerを使う場合、コンテナのポリシー(後者)を入れる。

  • AmazonKinesisVideoStreamsFullAccess
  • AmazonEC2ContainerRegistryPowerUser

アクセスキー、シークレットアクセスキーを入手したら完了。

ラズパイ側の設定(dockerを使わない場合)

dockerを使わない場合ビルドが長いので覚悟しておく。

各種ライブラリをインストール

sudo apt-get install libssl-dev libcurl4-openssl-dev liblog4cplus-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base-apps gstreamer1.0-plugins-bad gstreamer1.0-plugins-good gstreamer1.0-plugins-ugly gstreamer1.0-tools

producer SDKをクローン

git clone https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp.git
mkdir -p amazon-kinesis-video-streams-producer-sdk-cpp/build
cd amazon-kinesis-video-streams-producer-sdk-cpp/build

ビルド

cmake .. -DBUILD_GSTREAMER_PLUGIN=ON
make

しばし待つ

パスを通す

export GST_PLUGIN_PATH=$GST_PLUGIN_PATH:`pwd`
echo $GST_PLUGIN_PATH

kvssinkが入っているか確認

ここでkvssinkの情報が見れない場合はビルドが落ちているかパスが通っていないので前の手順を確認

gst-inspect-1.0 kvssink

bashrcにAWSのcredentialsを記述

// ~/.bashrcに追記
export AWS_ACCESS_KEY_ID=<access key>
export AWS_SECRET_ACCESS_KEY=<secret>

export AWS_REGION=<region>

ストリーミング開始

このコマンドでGstreamerがカメラから動画を取得し、kinesisに渡すようになる。

<your stream name>のところにはAWS consoleで作成したストリーム名を入れる。

gst-launch-1.0 v4l2src do-timestamp=TRUE device=/dev/video0 ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 ! omxh264enc control-rate=1 target-bitrate=5120000 periodicty-idr=45 inline-header=FALSE ! h264parse ! video/x-h264,stream-format=avc,alignment=au,width=640,height=480,framerate=30/1,profile=baseline ! kvssink stream-name="<your stream name>" access-key="${AWS_ACCESS_KEY_ID}" secret-key="${AWS_SECRET_ACCESS_KEY}" aws-region="${AWS_REGION}"

ラズパイ側の設定(dockerを使う場合)

docker, docker-composeはaptかなんかで事前に入れておく。

aws ecr get-login --no-include-email --region us-west-2 --registry-ids 546150905175
// dockerログインコマンドがもらえるので、suduつけてそのまま実行

// イメージを取得
sudo docker pull 546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-raspberry-pi:latest

// どのカメラ使うか確認しておく(ex. /dev/video0)
gst-device-monitor-1.0

起動が楽かと思いdocker-compose.ymlを作ってみた。

version: '3'

services:
  kvs:
    image: "546150905175.dkr.ecr.us-west-2.amazonaws.com/kinesis-video-producer-sdk-cpp-raspberry-pi:latest"
    volumes:
      - "/opt/vc:/opt/vc"
    devices:
      - "/dev/video0:/dev/video0"
      - "/dev/vchiq"

ストリーミング開始

docker-compose run kvs gst-launch-1.0 v4l2src do-timestamp=TRUE device=/dev/video0 \
  ! videoconvert ! video/x-raw,format=I420,width=640,height=480,framerate=30/1 \
  ! omxh264enc control-rate=1 target-bitrate=5120000 periodicty-idr=45 inline-header=FALSE \
  ! h264parse ! video/x-h264,stream-format=avc,alignment=au,width=640,height=480,framerate=30/1,profile=baseline \
  ! kvssink \
  stream-name=roomba-demo-stream \
  access-key="${AWS_ACCESS_KEY_ID}" \
  aws-region="${AWS_REGION}" \
  secret-key="${AWS_SECRET_ACCESS_KEY}" \
  content-type=video/h264

配信されていることを確認

AWS Console > Kinesis Video Streams > メディア再生

から、ラズパイのカメラ映像が見えていることを確認。

webページで映像を受け取る

credentials.jsとして保存

const AWS_REGION = '';
const AWS_STREAM_NAME = '';
const AWS_ACCESS_KEY_ID = '';
const AWS_SECRET_ACCESS_KEY = '';

index.htmlとして保存

<!DOCTYPE html>
<html>

<head>
    <link href="https://vjs.zencdn.net/7.7.5/video-js.css" rel="stylesheet" />
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.642.0.min.js"></script>
    <title>Viewer</title>
    <script src="credentials.js"></script>
</head>

<body>
<video id="videojs" class="player video-js vjs-default-skin" data-setup='{"fluid": true}' controls autoplay muted></video>

<script src="https://vjs.zencdn.net/7.7.5/video.min.js"></script>
<script>
window.addEventListener("unhandledrejection", function (event) {
  console.warn("WARNING: Unhandled promise rejection. Shame on you! Reason: "
    + event.reason);
  location.reload()
});
window.onerror = (message, file, lineNo, colNo, error) => {
  console.error('window.onerror', message, file, lineNo, colNo, error);
  location.reload()
}

async function getURL() {
  const accessKeyId = AWS_ACCESS_KEY_ID;
  const secretAccessKey = AWS_SECRET_ACCESS_KEY;
  const region = AWS_REGION;
  const streamName = AWS_STREAM_NAME;

  const options = {
    accessKeyId: accessKeyId,
    secretAccessKey: secretAccessKey,
    region: region,
  }
  const kinesisVideoClient = new AWS.KinesisVideo(options);
  const kinesisVideoArchivedMediaClient = new AWS.KinesisVideoArchivedMedia(options);

  const e = await kinesisVideoClient.getDataEndpoint({
    APIName: 'GET_HLS_STREAMING_SESSION_URL',
    StreamName: streamName
  }).promise();
  kinesisVideoArchivedMediaClient.endpoint = new AWS.Endpoint(e.DataEndpoint);

  const d = await kinesisVideoArchivedMediaClient.getHLSStreamingSessionURL({
    DisplayFragmentTimestamp: 'ALWAYS',
    StreamName: streamName
  }).promise();
  return d.HLSStreamingSessionURL;
}

document.addEventListener('DOMContentLoaded', async () => {
  const url = await getURL();
  const player = videojs('videojs');
  player.src({
    src: url,
    type: 'application/x-mpegURL'
  });
  player.on('error', function() {
    console.log(player.error());
    location.reload();
  });
  setInterval(() => {
    const t = player.currentTime();
    console.log("current Time is "+t +" seconds");
  }, 5000)
});
</script>
</body>

</html>
<style>
body {
  background-color: black;
}
</style>

参考

https://docs.aws.amazon.com/ja_jp/kinesisvideostreams/latest/dg/examples-gstreamer-plugin.html

https://github.com/awslabs/amazon-kinesis-video-streams-producer-sdk-cpp


Related Articles