OpenAIExpo2026/01/06 14:30

The offline first, multilingual audio tour app built with Expo

要点だけを先に読めるように短く再構成したセクションです。

元記事

Quick Digest

要約

要点だけを先に読めるように短く再構成したセクションです。

openaijamodel: gpt-5-mini-2025-08-07

Expoで構築したオフラインファーストの多言語オーディオツアーアプリ

Key Points

  • オフライン優先設計
  • iOSファイル検証実装
  • expo-locationで高精度監視

Summary

KuratourはExpo SDK上で構築された多言語・GPS連動のオフライン優先オーディオツアーアプリです。expo-file-systemで地図タイルや画像、音声を事前ダウンロードし、expo-sqliteでメタデータとユーザープログレスを管理。expo-locationの高精度バックグラウンド位置監視で場所に応じた自動再生を行い、expo-audioでレイヤードされた音声再生を実現しています。iOSのアップデートでファイルが消失する問題には、expo-applicationによるバージョン検知とファイル整合性チェックで対処します。

Key Points

  • コアモジュール
    • expo-location: 高精度の位置監視(watchPositionAsync, distanceInterval/timeInterval)
    • expo-file-system: CDNからMapboxタイル・MP3・画像を事前ダウンロード
    • expo-sqlite: ダウンロード済みツアー、ローカルURI、訪問履歴、スキーマ版管理
    • expo-audio / expo-video / @rnmapbox/maps: マルチメディア再生とオフライン地図
  • オフライン実装の流れ
    • ダウンロード順序: ルート→メイン画像→各ロケーションの音声/背景を逐次同期
    • ダウンロード後にローカルURIをSQLiteへ保存し、完全オフライン起動を保証
    • useOfflineDetectorカスタムフックで画面フォーカス時にSQLiteを優先チェック
  • データ整合性とiOSの落とし穴
    • アプリ版の変化をexpo-applicationで検知し、recheckDownloadedContentでファイル存在チェック
    • 欠損が見つかればバックグラウンドで再ダウンロード
    • SQLiteはアプリアップデートで保持されるが、Documents内ファイルはパス変動で欠損し得る点に注意
  • 実装上の実務的アドバイス
    • DBはスキーマ版管理+マイグレーションを必須にする(例: currentVersion制御)
    • ファイル操作はローカルのドキュメント構造をリモートとミラーリングして扱う
    • 位置監視は必要な精度/バッテリートレードオフを明示し設定(例: Accuracy.High, distanceInterval:1)
    • 音声はローカルURIを直接Audioコンポーネントに渡し、レイヤー制御で雰囲気演出

Full Translation

翻訳

原文の流れを保ったまま読める翻訳セクションです。

openaijamodel: gpt-5-mini-2025-08-07

Expoで作られたオフラインファーストの多言語オーディオツアーアプリ

Users • React Native • Development • 2026-01-06 • 11分読み物

Clinton Forster(ゲスト著者)

KuratourがどのようにExpoとexpo-audioを使い、オフラインファーストのアーキテクチャでGPSトリガーされたオーディオツアーとツアーオペレーター向けのホワイトラベルアプリを実現しているかを紹介します。Kuratourは、オーストラリア発のフルスタック開発者Clinton Forsterによるアプリで、2025年のAdventure Tourism Awardsで2025 Innovation Awardを受賞しました。

イントロダクション

旅は発見の連続であるべきで、手間やローミング料金、通信状況に邪魔されるべきではありません。多くの旅行者は高いローミング費用や不安定な受信、厳格なツアースケジュールに縛られています。Kuratourはこれを変えるため、スマートフォンを個人用の位置認識型ガイドに変え、世界のどこでも動作するよう設計されています(電波の届かない場所でも動作します)。

Kuratourのビジョン

KuratourはExpoで完全に構築された多言語対応のGPS駆動オーディオツアーアプリです。リアルタイムの位置トリガー、オフライン地図、AI生成ルートにより、徒歩やドライブの没入型体験を提供します。現在は自社プラットフォームだけでなく、オーストラリアをはじめとしたツアーオペレーター向けのホワイトラベルアプリ群にも採用されています。

この記事では、Expo SDKをどのように活用して「オフラインファースト」の課題を解決したか、そして新しいexpo-audioライブラリで現代的なオーディオエンジンをどのように構築したかを解説します。

Expoの基盤:大規模なモダンReact Native

Kuratourは新しいアーキテクチャ上のExpo SDKで完全に構築されており、ファーストパーティモジュールとコミュニティパッケージを組み合わせてネイティブ品質の体験を提供しています。

  • コアモジュール
    • expo-location:リアルタイムGPSトラッキングと領域ベースのトリガー
    • expo-file-systemexpo-sqlite:オフラインデータキャッシュとメディアストレージ
    • expo-audio:スムーズな多言語再生
    • expo-video:導入用の多言語説明チュートリアル
    • expo-splash-screen:起動時の見栄えの良い体験
    • expo-apple-authentication:iOSでのシームレスログイン
    • expo-application:アプリバージョンの確認(オフラインコンテンツの整合性チェックのため)
    • @rnmapbox/maps:対話的でオフライン対応の地図表示

オフラインファースト体験の構築

Kuratourにとって「オフラインファースト」は単なる機能ではなく、コア要件です。旅行者は遠隔地で受信を失ったり、ローミング費用を避けるためにデータ通信を切ることが多いため、次の対策を講じています。

  • 地図タイル、画像、オーディオは事前にダウンロードしておく(expo-file-systemを利用)
  • メタデータや訪問履歴はローカルに保存する(expo-sqliteを利用)
  • 接続状態を検知してオンライン/オフラインを自動切替する
  • expo-locationによるリアルタイムGPSトリガーで、ナレーションを正確なタイミングで再生する

ステップ1:SQLiteで構造化データを管理する

expo-sqliteを用いて、ダウンロード済みツアー、ユーザーの進捗、ローカライズ設定を追跡します。マイグレーションに対応するためにスキーマバージョンを管理しています(例:currentVersion = 3)。主な役割は次のとおりです。

  • データベースを開く(例:openDatabaseSync("db")
  • スキーマバージョンをチェックして必要なマイグレーションを適用
  • ツアーオブジェクトをJSON文字列として保存するためのsetOfflineData(tourID, offlineData)を提供

ステップ2:アセットダウンロードのオーケストレーション

ユーザーが「Download」をタップしたとき、Mapboxタイル、MP3、高解像度画像など複数リソースを同期する必要があります。expo-file-systemを使ってリモートのディレクトリ構造をローカルにミラーリングします。実装のポイントは:

  • CDN上のURLをキーから決定する
  • ドキュメントディレクトリ配下にサブディレクトリを作成して保存する(ユーザーの許可を都度取得せずに保管可能)
  • ローカルに存在しないファイルのみをダウンロードする(File.downloadFileAsync相当)
  • ローカルURIを<Audio><Image> コンポーネントに渡せるように保存する

ステップ3:UIとの統合

TourDownloadコンポーネント内では、プロセスを順次実行します。最初に地図ルートを取得し、次にメイン画像をダウンロードし、最後にツアー内の各ロケーションについて音声と背景トラックを取得します。完了後、ローカルファイルURIをSQLiteに保存して、ネットワーク接続がなくてもアプリが動作するようにします。

ステップ4:カスタムフックでのスマートな切替

ローカル保存が完了したら、どのソースを優先するかをアプリが判断する必要があります。useOfflineDetectorというカスタムフックを作り、useFocusEffect(React Navigation)を利用して、ユーザーがツアーページに遷移するたびにSQLiteを先にチェックするようにしています。主な挙動は次のとおりです。

  • getDatabaseService()でDBインスタンスを取得
  • getOfflineData(tourID)の結果が存在すればオフライン利用可能と判断
  • スクリーンがフォーカスされるたびにチェックを再実行

iOSアップデート時のデータ整合性の扱い

iOSでオフラインファーストアプリを作る際のよくある落とし穴は、アプリのアップデート時にDocumentsディレクトリ内のファイルパスが変わったり、ファイルが意図せず削除/孤立する挙動です。SQLiteは通常持ちこたえますが、expo-file-systemで保存したファイルが見つからないと、ユーザーは「ダウンロード済み」ツアーを開いたときに音声が欠落していることに気付きます。これを防ぐために、KuratourではContent Validation Bridgeを実装しています。

ステップ1:アップデートの検知

expo-applicationを使い、現在実行中のアプリバージョン(Application.nativeApplicationVersion)と、ローカルストレージに保存したlastCheckedVersionを比較します。差異がある場合はバリデーションをトリガーします。

ステップ2:ファイルシステムの検証

recheckDownloadedContentは、SQLiteでオフラインフラグの付いた全ツアーを巡回し、ファイルシステム上に資産が実際に存在するか確認します。メイン画像や最初のオーディオストップが1つでも欠けていれば、バックグラウンドで再ダウンロードを行います。

  • expo-file-systemのファイル存在チェックを行う
  • 不足があれば自動的に再ダウンロードをキューに入れる

発見を促進するためのexpo-location活用

Kuratourの魔法は「ハンズフリー」モードにあります。旅行者がポケットにスマホを入れたまま、自動的に座標に基づいてストーリーが再生されるようにしたい。これを実現するために、権限管理と高精度バックグラウンド購読を扱うカスタムフックuseLocationを作りました。

位置監視の実装ポイント:

  • Location.watchPositionAsyncで数秒ごと、あるいは1メートルの移動ごとに更新を受け取る
  • accuracy: Location.Accuracy.HightimeIntervaldistanceIntervalを調整してウォーキングツアーの精度を確保
  • フォアグラウンドパーミッションを要求し、許可がなければ購読を開始しない

expo-audioでのレイヤードサウンドのオーケストレーション

Kuratourの体験は単にテキストを読むことではなく、雰囲気を作ることにあります。ナレーション、背景アンビエンス、効果音を重ね合わせ、音量やパンをリアルタイムで制御し、シームレスなクロスフェードを行うためにexpo-audioを利用しています。音声はローカルURIを取得して各オーディオトラックを個別に扱い、以下のような制御を行います:

  • ナレーショントラックと背景トラックの独立した再生/停止/フェード
  • 場所や方角に応じたパンや音量の調整(定位効果)
  • 言語や声の切替(多言語対応)をシームレスに行うためのプリロード

まとめ

KuratourはExpo SDKの力を引き出し、厳しいオフライン要件とロケーション駆動の体験を両立させたアプリです。expo-sqliteでのローカルデータ管理、expo-file-systemによる事前ダウンロード、expo-locationの高精度トラッキング、そしてexpo-audioによる層状オーディオ処理を組み合わせることで、世界中のどこでも動作するハンズフリーの多言語オーディオツアーが実現できました。