Raspberry Pi と Web カメラ、生成 AI を使ってショート動画とベストショットを撮影できるカメラスポットを作ってみた!

2024-10-03
デベロッパーのためのクラウド活用方法

Author : 菅沢 佑太

みなさん、こんにちは !
夏の暑さも少し和らいできて、これからは紅葉の季節ですね。
自分は日本の風光明媚な場所を巡ることが好きで、今年の秋もいろんな場所に遊びに行こうと思っています。

景色の良い旅行先に行くと、「ここで写真撮りたい !」と思う撮影スポットは数多くありますが、肝心の撮影環境が整備されていない場合も多いですよね。なので、今回は AWS の IoT サービスを作って観光地の撮影スポットにピッタシな、 “思い出カメラ” を作ってみました !

このデモでは、「Web カメラで撮影した 10 秒動画」と、動画から切り出した最大 20 枚の画像のうち生成 AI が最も良いと選んだ「ベストショット 1 枚」とその「選択理由」、およびそれらの動画と画像をダウンロードするための QR コードがモニターに表示されます。

観光客は撮影スポットにあるボタンを押して、思い出として残したい動画を撮影します。その後、動画とベストショット 1 枚をお手持ちのスマートフォンですぐにダウンロードして楽しむことが可能です。

ご注意

本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。

*ハンズオン記事およびソースコードにおける免責事項 »

この記事のデモを無料でお試しいただけます »

毎月提供されるデベロッパー向けアップデート情報とともに、クレジットコードを受け取ることができます。 


1. アーキテクチャ

全体のアーキテクチャは以下の図のようになります。
デモでは、観光地に設置した Web カメラ、小型 PC (Raspberry Pi 等)、モニター、ボタンの 4 つを使います。以下のフローで処理が進んでいきます。

  1. ユーザーがボタンを押すと、 Web カメラを通して 10 秒間の動画が撮影され、Amazon Kinesis Video Streams に送られます。
  2. 10 秒間の動画を撮影後、ボタンを押した時のタイムスタンプとユニーク ID が AWS IoT Core に MQTT のトピックとしてパブリッシュされます。
  3. パブリッシュされたトピックを元に、AWS IoT Core ルール で AWS Lambda 関数 (GenerateClipAndImages) が起動します。この AWS Lambda 関数は、以下のフローで処理を行います。
    1. ボタン押下時のタイムスタンプを プロデューサータイム として設定し、10 秒間の動画を Kinesis Video Streams の getClip API で取得します。取得した動画を Amazon S3 に保存します。
    2. 同時間帯の動画から切り出した画像を getImages API で最大 20 枚まで取得します。20 枚の写真とプロンプト (例:複数枚の画像の中から最適な画像を 1 枚だけ選んでください) を Amazon Bedrock の invokeModel API のパラメータとして渡し、ベストショット 1 枚とその選択理由をレスポンスとして受け取ります。ベストショット 1 枚を Amazon S3 に保存します。
    3. Amazon DynamoDB に ベストショット 1 枚と 10 秒動画の署名付き URL を、ユニーク ID 、タイムスタンプと一緒にレコードに追加します。
  4. ユーザーの近くにはモニターがあり、Web ページが表示されています。 Web ページのバックエンド環境は AWS Amplify でホストされ、Amazon Cognito によるユーザー認証フローもあります。ユーザーは認証を済ませた後のページを見ているとします。
  5. ユーザーが Web ページの 更新ボタンを押すと、 Amazon API Gateway REST API にリクエストを送信し、その裏にある AWS Lambda 関数 (GetSignedURL) が起動します。この AWS Lambda 関数は、Amazon DynamoDB テーブルのタイムスタンプをソートキーとして、一番最新のレコードの内容をレスポンスとして返します。
  6. Web ページの JavaScript は AWS Lambda 関数より返されたレスポンスをもとに、署名付き URL からベストショット 1 枚と 10 秒動画がダウンロードできる QR コードを生成し、Web ページを描画します。

2. サンプルコード

はじめに、サンプルコードをダウンロード してください。workshop-builders-flash-v1.0.0.zip を展開すると以下のディレクトリ構造になっています。

workshop-builders-flash-v1.0.0
├── README.md
├── amplify
│   ├── lambda
│   │   └── GetSignedURLLambda.js
│   └── src
│       └── App.js
├── cdk
│   ├── README.md
│   ├── bin
│   │   └── workshop-cdk.ts
│   ├── cdk.json
│   ├── jest.config.js
│   ├── lambda
│   │   ├── GenerateClipAndImages.py
│   │   └── utils.py
│   ├── lib
│   │   └── workshop-cdk-stack.ts
│   ├── package-lock.json
│   ├── package.json
│   └── tsconfig.json
├── imgs
│   ├── aws-arch.png
│   └── sample.png
└── raspberrypi
    └── kvs-streamer.py

3. クラウドリソースの作成

今回は、Amazon Bedrock は us-east-1 リージョン、それ以外のリソースは ap-northeast-1 リージョンに作成します。

3-1. Amazon Bedrock の設定

Amazon Bedrock の初期設定として、ユーザーガイド に沿ってモデルアクセスの設定をしてください。今回使用するモデルは Anthropic の Claude 3 Sonnet です。モデルの用途を入力する部分は “bulders.flash workshop” としてください。

3-2. AWS Cloud Development Kit ( CDK ) の実行

今後は「 Raspberry Pi で実行するコマンド」と「開発用 PC で実行するコマンド」があるため、分かりやすくするために、ブログ記事中のコードブロックの冒頭に説明を記載します。
また、AWS CLI を実行する場合は、十分な権限を持つ AWS クレデンシャルを指定してください。

AWS Cloud Deployment Kit (CDK) を使うのが初めての場合は、AWS CDK 概要 (Basic #1)【AWS Black Belt】CDK の開発者ガイド などを参考に CDK をインストールしてください。すでに CDK がインスールされていれば、以下のコマンドでセットアップできます。

Node.js のバージョンは v20.11.1 を使用しています。

# これは開発用PCで実行するコマンドです
# 事前に十分な権限を持つAWSクレデンシャルを指定してください

cd workshop-builders-flash-v1.0.0/cdk
npm ci

# ap-northeast-1 でCDKの使用が初めての場合は以下のコマンドを実行してください。
cdk bootstrap 

cdk deploy

これで、アーキテクチャ図のうち AWS Amplify の範囲を除いたクラウドリソースが立ち上がります。

AWS CDK で立ち上がった AWS リソースは、AWS CloudFormation コンソールのスタックからも確認することができます。なお、Raspberry Pi で実行するコマンド用の AWS IAM ユーザーは作成されませんので、必要に応じて皆様側でご準備ください。

なお、当デモで利用する Amazon Bedrock にインプットするプロンプトは cdk/lib/workshop-cdk-stack.ts の「BEDROCK_PROMPT」に以下のように書かれています。Anthoropic Claude 3 では、プロンプトに XML タグ (<file_name> など) を利用することができるので、これを活用して皆様もプロンプトエンジニアリングに挑戦しても楽しいかもしれません。Anthoropic Claude のプロンプトエンジニアリングのやり方 をご参考ください。

# これはサンプルコードの説明です
# cdk/lib/workshop-cdk-stack.ts

const BEDROCK_PROMPT = "あなたはプロのフォトグラファーで、写真選びが得意です。\
      送った複数枚の写真のうち、最もベストな写真を1枚だけ選び、<file_name>にファイル名を記載しなさい。\
      最もベストな写真を選ぶ基準は<bar>を参考にしなさい。なお、<bar>のうち数字が小さいものほど優先順位が高いと思いなさい。\
      その写真を選んだ理由を200文字以内で<reason>に日本語で、楽しそうに書いてください。それ以外の内容を出力することは許しません。\
      理由に「基準を満たしていたから使った」とは決して書かないでください。<bar>は隠された基準であり、<reason>に書いてはいけません。\
      <bar>\
      1: 写真の中に1人以上の人間が写っている場合、できるだけ全ての人間が目を開いている写真を選びなさい。\
      2: 写真の中に1人以上の人間が写っている場合、できるだけ全ての人間が笑顔である写真を選びなさい。\
      3: 写真の中に1人以上の人間が写っている場合、人間同士の雰囲気が最も和やかである写真を選びなさい。\
      4: ブレが少なく、解像感が高い写真を選びなさい。\
      </bar>" // Bedrock に写真と一緒に送るプロンプト(ベストショット選定基準)

4. デバイスの設定

映像を送るためのハードウェアは、 Raspberry Pi に USB 接続の Web カメラ を繋いだものを使用します。
なお、当デモでは再現性を重視して、ボタンの代わりに Raspberry Pi に接続したマウスの左クリックをボタン押下として扱います。

4-1. Amazon Kinesis Video Streams Producer SDK C++ のセットアップ

Amazon Kinesis Video Streams に動画を送るために、以下の手順で Raspberry Pi に Amazon Kinesis Video Streams の SDK とサンプルコード をインストールします。

なお、当デモでは「4 : デバイスの設定」を完了させた時点で、Raspberry Pi のファイルが以下の構造になることを想定しています。一部のファイルは省略して記載しています。

$HOME
├── certificate.pem
├── public.key
├── private.key
├── AmazonRootCA1.pem
├── kvs-streamer-iot-config.json
├── kvs-streamer-kvs-config.json
├── kvs-streamer.py
├── amazon-kinesis-video-streams-producer-sdk-cpp
│   └── build
│       └── kvs_gstreamer_sample
└── env
    └── bin
        └── activate

4-2. AWS IoT Core のセットアップ

以下の手順で AWS IoT Core の利用に必要な設定をします。Raspberry Pi の CLI 上で以下のコマンドを上から順番に実行してください。

# これはRaspberry Piで実行するコマンドです
# 事前に十分な権限を持つAWSクレデンシャルを指定してください

# 以下の変数は変更する必要はありません
THING_NAME="RaspberryPi-Device"
POLYCY_NAME="RaspberryPi-Policy"
CERTIFICATE_FILE="$HOME/certificate.pem"
PUBLIC_KEY_FILE="$HOME/public.key"
PRIVATE_KEY_FILE="$HOME/private.key"
ROOT_CA_FILE="$HOME/AmazonRootCA1.pem"
IOT_CLIENT_ID="RaspberryPi-Client"

aws iot create-thing \
--thing-name ${THING_NAME}

CERTIFICATE_ARN=$(aws iot create-keys-and-certificate --set-as-active \
 --certificate-pem-outfile ${CERTIFICATE_FILE} \
 --public-key-outfile ${PUBLIC_KEY_FILE} \
 --private-key-outfile ${PRIVATE_KEY_FILE} \
 --query 'certificateArn' --output text)

aws iot create-policy \
 --policy-name ${POLYCY_NAME} \
 --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:*", "Resource": "*" } ] }'

aws iot attach-policy \
 --policy-name ${POLYCY_NAME} \
 --target ${CERTIFICATE_ARN}

aws iot attach-thing-principal \
 --thing-name ${THING_NAME} \
 --principal ${CERTIFICATE_ARN}
 
wget https://www.amazontrust.com/repository/AmazonRootCA1.pem -O ${ROOT_CA_FILE}

IOT_ENDPOINT=$(aws iot describe-endpoint \
--endpoint-type iot:Data-ATS \
--query 'endpointAddress' \
--output text)

# 設定情報をkvs-streamer-iot-config.jsonに保存
cat << EOF > $HOME/kvs-streamer-iot-config.json
{  
   "CERTIFICATE_FILE": "$CERTIFICATE_FILE",
   "PRIVATE_KEY_FILE": "$PRIVATE_KEY_FILE",  
   "ROOT_CA_FILE": "$ROOT_CA_FILE",  
   "IOT_CLIENT_ID": "$IOT_CLIENT_ID",
   "IOT_ENDPOINT": "$IOT_ENDPOINT"
}
EOF

上記コマンドを実行することで、AWS IoT Core に Raspberry Pi が モノ としてセットアップされます。

4-3. Python実行環境のセットアップ

Raspberry Pi で Python の実行環境を作成します。Raspberry Pi の CLI 上で以下のコマンドを上から順番に実行してください。当デモでは Python の仮想環境を作成してそこに必要なモジュールをインストールしています。

# これはRaspberry Piで実行するコマンドです

export VIRTUAL_ENV_PATH=$HOME/env
python3 -m venv $VIRTUAL_ENV_PATH
source $VIRTUAL_ENV_PATH/bin/activate

pip install evdev boto3 uuid pytz awsiotsdk awscrt

Raspberry Pi に接続されている Web カメラの解像度と FPS の一覧を取得します。

# これはRaspberry Piで実行するコマンドです

v4l2-ctl --list-formats-ext

# 以下はレスポンスです
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YUYV' (YUYV 4:2:2)
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.100s (10.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.125s (8.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.200s (5.000 fps)
        [1]: 'MJPG' (Motion-JPEG, compressed)
                Size: Discrete 640x480
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 160x120
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 176x144
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 320x240
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 352x288
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.033s (30.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.033s (30.000 fps)

例えば上記の実行結果では、「YUYV」フォーマットで、「640 x 480」の解像度で「30.000 fps」が出力可能になります。当デモで利用する Amazon Kinesis Video Streams のサンプルアプリケーションでは、デフォルトで「YUYV」フォーマットが利用されるため、以下のように kvs-streamer-kvs-config.json に値を保存します。

なお、「KVS_GSTREAMER_SAMPLE_DIR」には Amazon Kinesis Video Streams のワークショップで使用した「amazon-kinesis-video-streams-producer-sdk-cpp」の build ディレクトリの場所を指定してください。

# これはRaspberry Piで実行するコマンドです
# <ここから> - <ここまで> の箇所のパラメータを変更して実行してください
# <ここから>
KVS_STREAM_RESOLUTION_WIDTH="640"
KVS_STREAM_RESOLUTION_HEIGHT="480"
KVS_STREAM_RESOLUTION_FPS="30"
KVS_GSTREAMER_SAMPLE_DIR="$HOME/amazon-kinesis-video-streams-producer-sdk-cpp/build"
# <ここまで>

# 設定情報をkvs-streamer-kvs-config.jsonに保存
cat << EOF > kvs-streamer-kvs-config.json
{  
   "KVS_STREAM_RESOLUTION_WIDTH": "$KVS_STREAM_RESOLUTION_WIDTH",
   "KVS_STREAM_RESOLUTION_HEIGHT": "$KVS_STREAM_RESOLUTION_HEIGHT",  
   "KVS_STREAM_RESOLUTION_FPS": "$KVS_STREAM_RESOLUTION_FPS",  
   "KVS_GSTREAMER_SAMPLE_DIR": "$KVS_GSTREAMER_SAMPLE_DIR"
}
EOF

これで準備は完了です。最後に、workshop-builders-flash-v1.0.0/raspberrypi/kvs-streamer.py を Raspberry Pi の任意のフォルダ(当デモは $HOME に置きます)に SCP コマンド等で転送しておき、以下のコマンドを実行してください。

# これはRaspberry Piで実行するコマンドです

# AWSクレデンシャルと、利用するPython仮想環境を指定します
export AWS_ACCESS_KEY_ID=
export AWS_SECRET_ACCESS_KEY=
export AWS_DEFAULT_REGION=ap-northeast-1
source $VIRTUAL_ENV_PATH/bin/activate

python ./kvs-streamer.py

実行に成功すると、以下のような標準出力が表示され、マウスクリックを待機する状態になります。この状態でマウスを左クリックすると、Python の サブプロセス で Amazon Kinesis Video Streams のサンプルアプリケーションが実行され、Amazon Kinesis Video Streams のストリームのエンドポイントに動画が送られます。この時に必要なパラメータは、デバイス固有のパラメータは kvs-streamer-iot-config.json と kvs-streamer-kvs-config.json から取得され、クラウド固有のパラメータは AWS Systems Manager Parameter Store から取得されます。

# これはRaspberry Pi で ./kvs-streamer.py を実行した後に表示される標準出力です
Connecting to <YOUR AWS IOT ENDPOINT>.iot.ap-northeast-1.amazonaws.com with client ID 'RaspberryPi-Client'...
Connected!
Mouse device found: /dev/input/event2
Device name: <YOUR MOUSE NAME>
Waiting for left mouse clicks...

Amazon Kinesis Video Streams で動画が送信し終わると、マウスクリック時のタイムスタンプ (JST) とユニーク ID が AWS IoT Core の MQTT トピックとしてパブリッシュされます。これで Raspberry Pi 側の処理は完了です。

Published: {'mouseClickTimeStamp': '2024-08-05 15:42:47 JST', 'uuid': '3aff678c-bf05-46a6-87a6-f118ab14e5a5'} to topic: workshop/ButtonClick

なお、cdk/lib/workshop-cdk-stack.ts に Amazon Kinesis Video Streams 関連のパラメータが定義されていますが、当デモのタイムラインは以下のようになっています。() はデフォルト値を表しています。

まず、ボタン (マウス) クリックした時の時刻を t = A とします。この時、時刻 t = A + KVS_GET_CLIP_START_TIME_DELAY (5) が GetClip API の開始時刻になります。つまり、ユーザはボタンを押してから KVS_GET_CLIP_START_TIME_DELAY (5) 秒間は録画開始まで準備時間があります。

その後、時刻 t = A + KVS_GET_CLIP_START_TIME_DELAY (5) +KVS_GET_CLIP_DURATION (10) が GetClip API の終了時刻になります。時刻 t = A + KVS_GET_CLIP_START_TIME_DELAY (5) + KVS_GET_CLIP_DURATION (10) + KVS_GET_CLIP_END_BUFFER (5) には ./kvs_gstreamer_sample が終了し、終了後に 時刻 t = A が MQTT トピックとしてパブリッシュされ、AWS IoT Core ルールによって、AWS Lambda 関数 (GenerateClipAndImages) が起動します。

上記の値は任意の値に変更して良いですが、./kvs_gstreamer_sample を実行してから Amazon Kinesis Video Streams に動画が送られるまでの間にはラグが発生しているので、実際の環境に合わせて、値を変えてみてください。
なお、私が使用した Raspberry Pi 4 Model B + 良好な Wi-Fi の環境では、マウスクリックから動画が送られるまで約 4 秒でした。


5. Webフロントエンドの設定

撮影した画像と動画や、ダウンロード用の QR コードを表示する Web フロントエンド を設定します。今回は、AWS Amplify を利用してリソースを用意します。

以下のコマンドを、開発者用 PC で実行してください。アプリケーション名は「workshop-amplify」とします。

# これは開発用PCで実行するコマンドです
# 事前に十分な権限を持つAWSクレデンシャルを指定してください

npm install -g @aws-amplify/cli
npm install aws-amplify @aws-amplify/ui-react
npm install aws-amplify @aws-amplify/api
npm install qrcode.react

# React のサンプルアプリケーションを作成します
cd workshop-builders-flash-v1.0.0
npx create-react-app workshop-amplify
cd workshop-amplify

Amplify CLI で AWSリソース を作成していきます。

# これは開発用PCで実行するコマンドです
amplify init

# 以下は amplify の設定です
? Initialize the project with the above configuration? Yes
Using default provider  awscloudformation
? Select the authentication method you want to use: AWS access keys
? accessKeyId:  ********************
? secretAccessKey:  ****************************************
? region:  ap-northeast-1
✔ Help improve Amplify CLI by sharing non-sensitive project configurations on failures (y/N) · yes

Amplify Auth を設定します。

# これは開発用PCで実行するコマンドです
amplify add auth

# 以下は amplify の設定です
Do you want to use the default authentication and security configuration? Default configuration
 Warning: you will not be able to edit these selections. 
 How do you want users to be able to sign in? Username
 Do you want to configure advanced settings? No, I am done.

Amplify API を設定します。Amazon API Gateway には AWS_IAM 認証を設定し、Web ページにログインしたユーザーだけが API を実行できるようにします。
「Provide a friendly name for your resource to be used as a label for this category in the project」には「workshop」と入力します。

# これは開発用PCで実行するコマンドです
amplify add api

# 以下は amplify の設定です
? Select from one of the below mentioned services: REST
✔ Provide a friendly name for your resource to be used as a label for this category in the project: · workshop
✔ Provide a path (e.g., /book/{isbn}): · /items
Only one option for [Choose a Lambda source]. Selecting [Create a new Lambda function].
? Provide an AWS Lambda function name: GetSignedURL
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Hello World

? Do you want to configure advanced settings? No
? Do you want to edit the local lambda function now? No

✔ Restrict API access? (Y/n) · yes
✔ Who should have access? · Authenticated users only
✔ What permissions do you want to grant to Authenticated users? · create, read, update, delete
✔ Do you want to add another path? (y/N) · no

Amplify Hosting を設定します。

# これは開発用PCで実行するコマンドです
amplify add hosting

# 以下は amplify の設定です
✔ Select the plugin module to execute · Amazon CloudFront and S3
✔ hosting bucket name · workshop-<YOUR NUMBER>-hostingbucket

完了後、workshop-amplify/amplify/backend/function/GetSignedURL/src に AWS Lambda 関数が入っているので、index.js の中身を workshop-builders-flash-v1.0.0/amplify/lambda/GetSignedURLLambda.js の中身に置き換えます。

workshop-amplify/src/App.js の中身を workshop-builders-flash-v1.0.0/amplify/src/App.js の中身に置き換えます。App.js の以下の箇所を、amplify add api で 設定した API 名 と パス に変更します。

# 以下のサンプルコードを編集してください
# /workshop-amplify/src/App.js

# API Gateway で設定した API 名とパスを設定してください
const API_NAME = "workshop";
const API_PATH = '/items';

完了後、amplify push して AWS リソース を作成します。

# これは開発用PCで実行するコマンドです
amplify push

# 以下はレスポンスです
✔ Successfully pulled backend environment dev from the cloud.

    Current Environment: dev
    
┌──────────┬──────────────────┬───────────┬───────────────────┐
│ Category │ Resource name    │ Operation │ Provider plugin   │
├──────────┼──────────────────┼───────────┼───────────────────┤
│ Auth     │ workshop58d0c59c │ Create    │ awscloudformation │
├──────────┼──────────────────┼───────────┼───────────────────┤
│ Function │ GetSignedURL     │ Create    │ awscloudformation │
├──────────┼──────────────────┼───────────┼───────────────────┤
│ Api      │ workshop         │ Create    │ awscloudformation │
├──────────┼──────────────────┼───────────┼───────────────────┤
│ Hosting  │ S3AndCloudFront  │ Create    │ awscloudformation │
└──────────┴──────────────────┴───────────┴───────────────────┘
✔ Are you sure you want to continue? (Y/n) · yes

REST API endpoint: https://<YOUR API ENDPOINT>.execute-api.ap-northeast-1.amazonaws.com/dev
Hosting endpoint: https://<YOUR HOSTING ENDPOINT>.cloudfront.net

“Hosting endpoint” は Web ページの URL になるので、メモをしておきます。
Amplify publish をします。

# これは開発用PCで実行するコマンドです
amplify publish

# 以下はレスポンスです
✔ Uploaded files successfully.
Your app is published successfully.
https://<YOUR HOSTING ENDPOINT>.cloudfront.net

予想外のユーザーによる Web サイトの利用を防止するために、作成した Webページ にはユーザー作成機能 (サインアップ) を意図的に無くしています。そのため、Amplify Auth で設定した Amazon Cognito ユーザープール ID を使用して、CLI で Amazon Cognito ユーザーを作成します。マネジメントコンソールで、Amazon Cognito → ユーザープール名を選択 → ユーザーを作成 でも実施可能です。

# これは開発用PCで実行するコマンドです
cd workshop-amplify
COGNITO_USER_POOL_ID=$(grep -oP '"aws_user_pools_id":\s*"\K[^"]+' ./src/aws-exports.js)

# Amazon Cognito ユーザーのログイン情報を記入後、実行してください
USER_NAME="workshop-user"
USER_EMAIL="hogehoge@hoge.com"
TEMPORARY_PASSWORD="Workshop-Pw-202408"

aws cognito-idp admin-create-user \
  --user-pool-id ${COGNITO_USER_POOL_ID} \
  --username ${USER_NAME} \
  --temporary-password ${TEMPORARY_PASSWORD} \
  --user-attributes Name=email,Value=${USER_EMAIL} Name=email_verified,Value=true \
  --message-action SUPPRESS

ユーザーの作成完了後、https://<YOUR HOSTING ENDPOINT>.cloudfront.net にアクセスしてログインしてください。
以下のような画面が出れば成功です ! まだ動画を撮影していないため、「Failed to retrieve data」と表示されていて大丈夫です。

なお、ユーザー作成機能 (サインアップ) を有効化したい場合は、App.js の 以下の箇所の「hideSignUp」を「false」に変更してください。

# 以下のサンプルコードを編集してください
# /workshop-amplify/src/App.js

# デフォルト設定では true になっています
export default withAuthenticator(App, {
  signUpAttributes: [],
  hideSignUp: true
});

6. テスト実行

それでは実行してみましょう。
Webカメラの前に立ってマウスを左クリックして、動画を撮影します。
マウスクリック後、30 秒ほど後に Web ページ の更新ボタンを押すと以下のような表示が出ます。

今回は、AWS Japan 目黒オフィスから見える、東京の街並みを撮影してみました。
Amazon Bedrock の気の利いたコメントが嬉しいですね !

QR コードは Amazon S3 署名付き URL を表しているので、携帯電話で読み取ることで写真と画像のダウンロードが可能です。なお、上記に掲載している QR コードにぼかしが入っていますが、実際には鮮明に表示されます。
有効期限は cdk/lib/workshop-cdk-stack.ts の「S3_SIGNED_URL_DURATION」で秒単位で設定できます。当デモでは 3,600 秒 (1 時間) としています。

# これはサンプルコードの説明です
# cdk/lib/workshop-cdk-stack.ts

# デフォルト設定では 3,600 秒になっています
const S3_SIGNED_URL_DURATION = '3600' // S3署名付きURLの有効時間(s)

7. まとめ

今回は AWS の IoT サービス と 生成 AI を活用して、観光地にピッタシなカメラソリューションを実装してみました。マルチモーダル対応の基盤モデルを利用することで、複数枚の写真から 1 枚を選定する基準を プロンプト という形で書くことができます。プロンプトエンジニアリング次第で、シーンに応じてベストショット選定の基準を変えることができるのは魅力的な点ですね。

当デモでは Web ページのデザイン等は拘っていませんが、もし当ソリューションを本格的に導入されたい方がいらっしゃいましたら、私までご連絡ください。皆さんの素敵な思い出が残れば幸いです。ありがとうございました!


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

菅沢 佑太
アマゾン ウェブ サービス ジャパン 合同会社
Public Sector, Central Government
Solutions Architect

公共部門のお客様のクラウド活用を支援しています。
IoT と AWS を組み合わせて、日常でちょっと役に立つソリューションを開発していくのが好きです。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する