はじめに
おつかれさまです。tyamonです。
SORACOM UG Hiroshima #10(2025年9月20日開催)のハンズオンパートで出た反省をもとに、スマホで撮った写真をSORACOM Harvest Filesへ送るアップローダアプリを、今回のSORACOM UG Explorer 2026(2026年10月31日開催)向けに作り直しました。この記事では、何を変えたか、なぜそうしたかをまとめます。
結論:インフラはAmplify Gen2でコード化し、画像はブラウザ側で縮小してから送る構成にしました。
UG Hiroshima #10のときは、AWSリソースを全部手動で作っていた
UG Hiroshima #10版は、Cognito、Lambda、API Gateway、S3、CloudFrontをマネジメントコンソールから1つずつ作っていました。当時のセットアップ手順書も、コンソールのクリック手順で書かれています。
動きはしますが、環境を作り直すたびに手順書を見ながらやり直すことになります。再現性も低く、設定の差分も残りません。
AWS CDKかAmplifyか。今回はAmplify Gen2にした
作り直しにあたって、AWS CDKとAmplifyのどちらにするか迷いました。このアプリはフロントが静的ファイル、バックエンドがLambda 1本とCognitoだけで、そこまでヘビーではありません。そこでAmplify Gen2で十分と判断しました。
構成は次のとおりです。
- 認証:Cognito(Amplify Gen2のauth)
- API:Lambda(Node.js / TypeScript)をAPI Gatewayの背後に配置
- フロント:Amplifyホスティングで配信
Amplify Gen2はTypeScriptでバックエンドを定義します。細かい設定が必要な箇所は、CDKのコードで上書きできます。今回もCognitoのパスワードポリシーやトークン有効期限、API Gatewayの追加は、backend.tsの中でCDKのコンストラクトを使って書いています。つまり「CDKかAmplifyか」は二択ではなく、Amplifyの中でCDKも使える、というのが実際の感覚です。
// amplify/backend.ts(抜粋)
const backend = defineBackend({ auth, uploadToHarvest });
// Cognitoの設定をCDKで上書き
const cfnUserPoolClient = backend.auth.resources.cfnResources.cfnUserPoolClient;
cfnUserPoolClient.idTokenValidity = 60;
cfnUserPoolClient.tokenValidityUnits = { idToken: 'minutes', accessToken: 'minutes' };
画像が大きくて、Fluxの推論に時間がかかった
UG Hiroshima #10のハンズオンでは、アップロードした画像のサイズが大きく、SORACOM FluxのAI推論に時間がかかってしまいました。結果が返ってくるまで待たされる参加者が出て、ハンズオンがスムーズに進みませんでした。スマホで撮った写真は、そのままだと容量が大きくなりがちです。
そこで今回は、アップロード前にブラウザ側で画像を縮小するオプションを用意し、初期状態でONにしました。長辺を1280pxに収め、JPEG品質85%で出力します。すでに小さい画像は、そのまま送ります。
// frontend/script.js(抜粋)Canvas APIで縮小
const ratio = maxLongSide / longSide;
canvas.width = Math.round(width * ratio);
canvas.height = Math.round(height * ratio);
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
縮小の実装は、最初はLambda側でやっていました。ただLambdaにネイティブ依存のライブラリを載せると、ビルド環境の違いで面倒が出ます。そのため、最終的にブラウザのCanvas APIに移し、Lambdaからは依存を外しました。送信するデータ量も減るので、アップロード自体も速くなります。
アップロード先を選べるようにして、表記のズレも直した
もう一つの反省は、アップロード先まわりです。
- アップロード先のフォルダを指定できるようにした。 入力したパスはブラウザのlocalStorageに記憶します。
- 完了メッセージの表記を、Harvest Filesの画面と合わせた。 以前はメッセージに
private/が付いていましたが、Harvest Filesのコンソールでは付きません。参加者が探したときに一致しないので、private/を外しました。
小さな修正ですが、ハンズオン中に「どこに入ったの?」と聞かれる回数が減ります。
イベント当日は、Kiro Crewにログを見させた
当日は、AmplifyにデプロイしたLambdaのCloudWatch Logsを、Kiro Crewのスケジュール機能で定期確認しました。2分ごとにスクリプトを走らせ、前回以降の新しいエラーだけを通知する形です。ログの時刻は日本時間に直して表示させました。
ログには個人を特定する情報を出していません。そのため「何人」ではなく「何回」しか数えられません。集計するときは、filter-log-eventsだとページングで取りこぼすため、CloudWatch Logs Insightsで数えるのが確実でした。
最終的には、スケジュール監視に頼り切るより、「直近のログはどう?」と聞いてその場で確認する使い方が中心になりました。
まとめ
UG Hiroshima #10の反省は、「手動構築」「画像が大きくて推論に時間がかかる」「表記と挙動のズレ」の3つでした。今回はAmplify Gen2でインフラをコード化し、ブラウザ側の画像縮小を初期ONにして、アップロード先の指定と表記も直しました。当日はログの確認をKiro Crewに任せました。
参考資料
- 同じ内容をコード中心にまとめたQiita記事
- アクションリファレンス: AI アクション(SORACOM Users)
- explorer2026-hands-on-flux-image-ai(ハンズオン資料)
この記事は tyamon(製造業の情シス)が実際に試した内容をもとに書いています。詳しくは運営者情報、ご質問はお問い合わせまで。

コメント