Echo SpotやEcho Showの様にディスプレイを持つEchoは動画を再生させることが出来ます。
既にAlexa向けのカメラはUSでいっぱい発売されていますが、これを自作してみようと思います。
カメラはラズパイ純正のカメラを利用しています。
全体像はこんな感じ
完成品が動いてる所
サンプルソース
Video Appで再生できる動画やオーディオ
ディスプレイ付Echoで使うdisplay templateの詳細については、この記事を見てください。
[Echo Showの表示を試してみる]
(https://qiita.com/sparkgene/items/75af623c47c57169624f)
Supported Video Formats and Resolutions
Streaming format | Accompanying audio format |
---|---|
HLS, MPEG-TS | AAC |
SmoothStreaming (SS), MP4, M4A | AAC, Dolby, Dolby Digital Plus |
- httpsを利用して動画が配信されれなければならない
- サポートしている拡張子:.mp4, .m3u8, .ts
- 対応コーデック:MPEG4 または H.264
- 推奨動画サイズ:640x480 または 1280x720
- 最大動画サイズ:1280x720
この条件をみたすようにraspberry piをセットアップします。
ラズパイのセットアップ
ラズパイにカメラを繋いで、そこから配信することで、echoからその映像が見れるようにします。
こちらの記事にやり方が公開されていたので、そちらを参考にしました。
Raspberry Pi のカメラモジュールでハイビジョン撮影して iOS に streaming 配信する
ラズパイは「2017-11-29-raspbian-stretch.img」を使っています。
$ uname -a
Linux raspberrypi 4.9.59-v7+ #1047 SMP Sun Oct 29 12:19:23 GMT 2017 armv7l GNU/Linux
ffmpegのインストール
$ sudo su
$ cd /usr/src
$ git clone --depth 1 git://source.ffmpeg.org/ffmpeg.git
$ cd ffmpeg
$ ./configure
$ make -j4
$ make install
nginxのインストール
$ apt-get install nginx
$ nginx -v
nginx version: nginx/1.10.3
$ chown -R pi /var/www/html
$ chgrp -R pi /var/www/html
ここで問題となるのが、echoではhttpsでのアクセスを必要とするので、SSL証明書が必要になります。
ラズパイ自体がインターネットからアクセスできるのであれば、直接Let's Encryptの設定ができるのですが、今回は外部に公開していないので、別のサーバで発行してそれをコピーする方法でSSL証明書を作成しました。
また、証明書を発行する際にドメインも必要なので、AWSのRoute53でローカルのIPと紐付けたレコードを追加しています。
ec2上でSSL証明書を発行
$ sudo su
$ yum install nginx
$ service nginx start
$ wget https://dl.eff.org/certbot-auto
$ chmod a+x certbot-auto
$ ./certbot-auto --no-bootstrap certonly --webroot -w /usr/share/nginx/html -d <使うドメイン> --email <自分のメアド>
これで、etc/letsencrypt/live/<使うドメイン>/
の中に以下の証明書が作られるので、それを全部ラズパイにコピーします。
- cert.pem
- chain.pem
- fullchain.pem
- privkey.pem
ラズパイ側
$ mkdir /etc/nginx/certs
$ cd /etc/nginx/certs
ココに、作成したSSL証明書を置きます。
サンプルのソースをgitからcloneしてそれを使用します。
$ cd /opt
$ git clone git@github.com:sparkgene/echo-pi-camera.git
$ cp /opt/echo-pi-camera/nginx/stream.conf /etc/nginx/sites-available/stream.conf
$ ln -s /etc/nginx/sites-available/stream.conf /etc/nginx/sites-enabled/stream.conf
/etc/nginx/sites-enabled/stream.conf
に自分のドメインを書きます。
server {
listen 443 ssl;
server_name <自分のドメイン>;
ラズパイにアクセスできるネットワーク上から実際にドメイン指定でアクセスできるかを確認します。
$ curl -I https://<自分のドメイン>/
HTTP/1.1 200 OK
Server: nginx/1.10.3
Date: Wed, 21 Mar 2018 07:10:09 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Wed, 21 Mar 2018 05:26:01 GMT
Connection: keep-alive
ETag: "5ab1ece9-264"
Accept-Ranges: bytes
これで、動画を配信する準備はできました。
Alexa Skillの作成
Alexa Skillはカスタムスキルを利用しますが、まだecho spotはまだ日本語対応していないので、US英語向けのSkillとして作成します。
skillの作成ではask cliを使っいますので、事前にAWSのクレデンシャルの登録をします。
ask cliで必要な権限は以下で公開されているので、この権限を持つアクセスキーを作成して、プロファイルを作成します。
https://developer.amazon.com/ja/docs/smapi/set-up-credentials-for-an-amazon-web-services-account.html
作業は、PC上で行ないます。
$ aws credential -p ask-cli
次にask cliをインストールしていなければ、インストールして初期設定を済ませます。
$ npm install -g ask-cli
$ ask init
$ ask init -l
Profile Associated AWS Profile
[default] ** NULL **
[us-alexa] "ask-cli"
プロフィル名は適宜自分の環境に合わせて下さい。
サンプルソースをコピーます。
$ git clone git@github.com:sparkgene/echo-pi-camera.git
$ cd echo-pi-camera/echo-pi-camera
lambda/custom/lambda_function.py
に映像のURLが書かれているので自分の環境に合わせて書き換えて下さい。
VIDEO_URL = "https://<自分のドメイン>/stream.m3u8"
askコマンドで、デプロイします。
$ ask deploy -p us-alexa
-------------------- Create Skill Project --------------------
Profile for the deployment: [us-alexa]
Skill Id: amzn1.ask.skill.
Skill deployment finished.
Model deployment finished.
Lambda deployment finished.
Your skill is now deployed and enabled in the development stage.
Try invoking the skill by saying “Alexa, open {your_skill_invocation_name}” or simulate an invocation via the `ask simulate` command.
完了すると、skillとlambdaファンクションが作られます。
lambdaファンクションで、runtimeが nodejs
になってしまうのが原因わからないのですが(誰か教えて)、これをpython 3.6
に変えます。
ラズパイ上で配信を開始
$ cd /opt/echo-pi-camera
$ sh ./stream.sh
ffmpeg version git-2018-03-21-7e0dc72 Copyright (c) 2000-2018 the FFmpeg developers
built with gcc 6.3.0 (Raspbian 6.3.0-18+rpi1) 20170516
configuration:
libavutil 56. 11.100 / 56. 11.100
libavcodec 58. 14.100 / 58. 14.100
libavformat 58. 10.100 / 58. 10.100
libavdevice 58. 2.100 / 58. 2.100
libavfilter 7. 13.100 / 7. 13.100
libswscale 5. 0.102 / 5. 0.102
libswresample 3. 0.101 / 3. 0.101
Input #0, h264, from 'pipe:':
Duration: N/A, bitrate: N/A
Stream #0:0: Video: h264 (High), yuv420p(progressive), 720x404, 25 fps, 25 tbr, 1200k tbn, 50 tbc
[stream_segment,ssegment @ 0x2b7b310] Opening '/var/www/html/segments/00000000.ts' for writing
Output #0, stream_segment,ssegment, to '/var/www/html/segments/%08d.ts':
Metadata:
encoder : Lavf58.10.100
Stream #0:0: Video: h264 (High), yuv420p(progressive), 720x404, q=2-31, 25 fps, 25 tbr, 90k tbn, 25 tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
[stream_segment,ssegment @ 0x2b7b310] Timestamps are unset in a packet for stream 0. This is deprecated and will stop working in the future. Fix your code to set the timestamps properly
[stream_segment,ssegment @ 0x2b7b310] Opening '/var/www/html/stream.m3u8.tmp' for writing
[stream_segment,ssegment @ 0x2b7b310] Opening '/var/www/html/segments/00000001.ts' for writing
[stream_segment,ssegment @ 0x2b7b310] Opening '/var/www/html/stream.m3u8.tmp' for writing
[stream_segment,ssegment @ 0x2b7b310] Opening '/var/www/html/segments/00000002.ts' for writing
配信が始まっている状態で、echoに対して alexa, open pi camera
と話しかけると、映像が表示されます。
こんな感じのアクセスログが残ってました。
192.168.3.32 - - [21/Mar/2018:09:20:37 +0000] "GET /stream.m3u8 HTTP/1.1" 200 275 "-" "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEORK Build/LVY48F)"
192.168.3.32 - - [21/Mar/2018:09:20:37 +0000] "GET /00000003.ts HTTP/1.1" 200 389536 "-" "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEORK Build/LVY48F)"
192.168.3.32 - - [21/Mar/2018:09:20:37 +0000] "GET /00000004.ts HTTP/1.1" 200 392356 "-" "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEORK Build/LVY48F)"
192.168.3.32 - - [21/Mar/2018:09:20:38 +0000] "GET /00000005.ts HTTP/1.1" 200 217140 "-" "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEORK Build/LVY48F)"
192.168.3.32 - - [21/Mar/2018:09:20:38 +0000] "GET /00000003.ts HTTP/1.1" 200 389536 "-" "Dalvik/2.1.0 (Linux; U; Android 5.1.1; AEORK Build/LVY48F)"
ffmpegのオプションで -segment_time 2
と -segment_list_size 5
を指定してるから、 stream.m3u8
に2秒のtsファイルが最大5個として順次書き換えられていきます。echo側からの読み込みは stream.m3u8
の先頭に書かれているtsファイルを順次読み込んでいくので、その分の遅延が発生します(最大、10秒ぐらい)。
これをもっとリアルタイムにするには、もっとチューニングが必要そうな感じですね。
Smart Home Skill
今回はカスタムSkillとして作成しましたが、実際はSmartHome Skillでも作れるので、自然な発話で考えると、SmartHome Skillの方が良いのかなと思います。
https://developer.amazon.com/docs/device-apis/alexa-camerastreamcontroller.html
今度は、SmartHome版にもチャレンジしようと思います。
参考にしたサイト
https://qiita.com/UedaTakeyuki/items/dbb466fd47fa32a57a4c
https://www.ffmpeg.org/ffmpeg-formats.html#segment_002c-stream_005fsegment_002c-ssegment
https://qiita.com/MashMorgan/items/56498f276c54406b1928