5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

スマホを使えない高齢者に防災情報をテレビで届けるシステムをAWSで作った

5
Posted at

はじめに

内閣府の調査によると、災害時に避難が遅れた理由として「情報が届かなかった」「操作がわからなかった」が繰り返し上位に挙がります。スマートフォンが普及しても、70〜80代の高齢者が緊急時に慣れないアプリを開くのは現実的ではありません。

テレビが防災情報端末になれば、この問題の大部分は解決できる。 その発想から SafeTV を開発しました。

Android TV や Fire TV Stick の普及により、Web アプリをテレビの HDMI から直接表示することが現実的になりました。専用アプリ不要で、ブラウザで動く Web アプリがそのままテレビで動作します。

デモ: https://safetv.eggsystems.jp
コード: https://github.com/kojiman55/safetv

デモ動画・機能

SafeTV メイン画面

SafeTV 避難アラート画面

初回起動時に都道府県と市区町村を選ぶだけで、以下がすべて自動で動きます。

  • YouTube 動画の連続再生(ニュース・天気・旅行・自然の 4 カテゴリ)
  • NHK ニュース自動スクロール(7件ずつ 30 秒ごとに更新)
  • 気象庁の 3 日間天気・気温をリアルタイム表示
  • 警戒レベル 3 以上の自動割り込みアラート(動画を強制中断して画面を占有)

技術スタック

レイヤー 技術
フロントエンド Next.js 16 / TypeScript
バックエンド AWS Lambda (TypeScript) / API Gateway / esbuild
インフラ AWS SAM / S3 / CloudFront / EventBridge
外部 API NHK Web API / 気象庁 API / YouTube RSS

Lambda は TypeScript を esbuild でバンドル(ビルド約 16ms)、Next.js は静的エクスポートで S3 + CloudFront から配信しています。

YouTube API を使わなかった理由と実装

公式の YouTube Data API v3 の代わりに RSS フィードを使いました。

https://www.youtube.com/feeds/videos.xml?channel_id=UCxxxxxxx

RSS フィードの利点:

  • API キー不要
  • 認証不要
  • クォータ制限なし

XML をパースして最新 10 本の動画 ID を取得するだけです。ただし 2018 年以前に作られた「レガシーチャンネル」にのみ対応しており、NHK・フジテレビ公式などは 404 を返します。

RSS_FAIL 404: NHK (UCip8ve30-AoX2y2OtAAmqFA)
RSS_FAIL 404: フジテレビ公式 (UC7_mFzmj89tqAqgpl5695QQ)

取得できなかったチャンネルは静かに除外する設計にしたため、フロントには常に再生可能なチャンネルだけが届きます。

Lambda のキャッシュ戦略

RSS フィードへのリクエストは Lambda のモジュールスコープにキャッシュを持たせています。

type CacheEntry = {
  videos: { id: string; title: string; description: string; channelName: string }[]
  expires: number
}
const rssCache = new Map<string, CacheEntry>()
const RSS_TTL = 10 * 60 * 1000 // 10分

async function fetchChannelVideos(id: string, name: string) {
  const now = Date.now()
  const cached = rssCache.get(id)
  if (cached && cached.expires > now) return { id, name, videos: cached.videos }

  // キャッシュ切れ or 初回: フェッチして保存
  const videos = await fetchRSS(id)
  rssCache.set(id, { videos, expires: now + RSS_TTL })
  return { id, name, videos }
}

Lambda コンテナはウォーム状態を一定時間保つため、10 分以内のリクエストはキャッシュから返ります。コンテナ再起動でキャッシュは消えますが、デモ用途では許容範囲です。

災害アラートの設計:「画面を乗っ取る」

気象庁の防災情報 API は EventBridge で 5 分ごとに叩き、結果を S3 に保存します。フロントは S3 キャッシュを読むだけなので、ユーザーアクセスのたびに気象庁サーバーを叩きません。

EventBridge(5分ごと)
  └─ Lambda → 気象庁API → S3 (alerts/latest-osaka.json)

ブラウザ(5分ごとにポーリング)
  └─ API Gateway → Lambda → S3 を読む

警戒レベル 3 以上を検知すると、動画もニュースも強制的に消えてアラート画面に遷移します。戻るボタンは意図的に存在しません。

useEffect(() => {
  if (alert.level >= 3) {
    localStorage.setItem('current_alert', JSON.stringify(alert))
    router.push('/alert')
  }
}, [alert, router])

アラート画面には「避難所に向かう」「救助を希望する」「家族に連絡して」の 3 ボタンだけが並びます。高齢者が緊急時に何をすればよいか迷わない設計です。

セットアップ:ドロップダウン 2 つだけ

都道府県を選ぶと市区町村リストが切り替わる、シンプルな 2 段階設定です。

const profile: UserProfile = {
  prefecture: pref.name,
  areaCode: pref.areaCode,    // 気象庁コード(天気・アラートに使用)
  city: selectedCity.name,
  cityCode: selectedCity.code, // JIS市区町村コード(避難所ナビ等で使用予定)
}

天気・アラートには都道府県レベルの気象庁エリアコード、将来の避難所ナビには JIS 市区町村コードを使う設計です。住所入力も位置情報も不要にしました。

画面レイアウトの設計方針

最初に決めたのはレイアウトでした。

  • 16:9 の比率
  • 左 60% に動画
  • 右 40% に情報パネル
  • 下部にチャンネルバー
  • ヘッダーに時計と地域名

この配置を決めた時点でコンポーネント構成がほぼ確定しました。制約(マウスなし・キーボードなし・ログインなし)を最初から受け入れることで、UI に迷う余地がなくなりました。

インフラ構成

ブラウザ(TV / PC)
    ↓
CloudFront + S3(Next.js 静的エクスポート)
    ↓
API Gateway + Lambda
    ↓
EventBridge(定期実行)→ 気象庁 API → S3 キャッシュ
                       → YouTube RSS フィード
                       → NHK Web API

インフラは AWS SAM でコード管理しており、デプロイはコマンド 1 つで完結します。月額コストは Route 53 の約 $0.50 のみです。

まとめ

テレビというフォームファクターは、制約が多い分だけ設計が楽でした。「マウスなし・キーボードなし・ログインなし」という 3 つの制約を最初から捨てることで、シンプルなものができました。

高齢者向けシステムの設計では、制約を「使えない機能」として扱うのではなく「設計の指針」として活用することで、むしろ使いやすいものが生まれると感じています。

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?