ラズパイにUSBで刺したwebカメラの映像をKinesis Video Streamsで配信する方法を解説。
試したのはラズパイだが、おそらくJetsonでも動く。
Management Console > Kinesis Video Streams > ビデオストリームを作成押下。ビデオストリームを作成する。ビデオストリーム名は後で使うのでメモ。
IAM > ユーザーを追加を押下。適当に埋めて行く。
アクセスの種類はプログラムによるアクセスを選択
アクセス許可の設定 > 既存のポリシーを直接アタッチから以下を追加しておく。後でラズパイ側の設定をするときに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
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の情報が見れない場合はビルドが落ちているかパスが通っていないので前の手順を確認
gst-inspect-1.0 kvssink
// ~/.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-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 > メディア再生
から、ラズパイのカメラ映像が見えていることを確認。
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