実装
AudioRecognition instanceの作成
SORIアプリケーション認証情報を使ってSORIAudioRecognizerを作成します。実際の認証情報を公開ソースコードにハードコードしないでください。リリース設定、セキュアストレージ、環境ごとのビルドプロセスを通じて読み込んでください。
次の例では、ソースコードに機密値が残らないように--dart-define値を使用します。
import 'package:sorisdk_flutter/sorisdk_flutter.dart';
const applicationId = String.fromEnvironment('SORI_APP_ID');
const secretKey = String.fromEnvironment('SORI_SECRET_KEY');
final recognizer = SORIAudioRecognizer(
applicationId: applicationId,
secretKey: secretKey,
);
await recognizer.configure();ローカルまたはCI環境から値を渡してアプリを実行します。
flutter run \
--dart-define=SORI_APP_ID=your-application-id \
--dart-define=SORI_SECRET_KEY=your-secret-keyWARNING
app_idとsecret_keyは、アプリをSORI API Serverで認証するための値です。実際の値をリポジトリ、サンプルアプリ、Issue、スクリーンショット、公開ドキュメントにコミットしないでください。
Web recognizer
ブラウザビルドには長期有効なSORI secret_keyを含めないでください。インストールでWeb bridgeを準備した後、アプリケーションサーバー上のephemeral key endpointを使用してrecognizerを作成します。
final recognizer = SORIAudioRecognizer.web(
applicationId: applicationId,
webAuth: SORIWebAuthOptions.ephemeralKeyEndpoint(
Uri.parse('/api/sori/ephemeral-key'),
requestCredentials: SORIWebRequestCredentials.sameOrigin,
),
);
await recognizer.configure();endpointは、他のアプリケーションAPIと同じsession、origin、CSRF、rate limit制御で保護してください。長期有効なsecret_keyはサーバーに保持しますが、applicationIdはブラウザアプリケーションにコンパイルされるためsecretではありません。endpointは短期有効なephemeral keyだけをブラウザに返します。Ephemeral Keyを参照してください。
認識イベントの受信
認識を開始する前にrecognizer.eventsを購読します。キャンペーン情報は、ネイティブプラットフォームイベントに応じてevent.campaignまたはイベントpayloadから取得できます。
import 'dart:async';
import 'package:sorisdk_flutter/sorisdk_flutter.dart';
late final SORIAudioRecognizer recognizer;
StreamSubscription<SORIRecognitionEvent>? subscription;
subscription = recognizer.events.listen((event) {
if (event.type == SORIRecognitionEventType.stateChanged) {
final state = event.payload['state'];
// STARTING、STARTED、stoppedの状態に合わせてUIを更新します。
}
final campaign = event.campaign;
if (campaign != null) {
// campaign.name、campaign.imageUrl、campaign.actionUrlを表示します。
final marker = campaign.trait?.marker;
if (marker != null) {
// このキャンペーンに付与されたオーディオマーカーcodeを必要に応じて使用します。
}
}
if (event.type == SORIRecognitionEventType.audioMarkerChanged) {
final marker = event.audioMarker;
// marker専用のUIや状態を更新します。
}
if (event.type == SORIRecognitionEventType.error ||
event.type == SORIRecognitionEventType.networkError) {
// アプリのエラーUIにevent.messageを表示します。
}
});現在のアクティビティセグメントの調整
キャンペーンイベントと認識イベントはオプションのevent.activityIdを公開し、 キャンペーンにはevent.campaign?.materialIdとevent.campaign?.trait?.markerが 含まれることがあります。最初のキャンペーンイベントはすぐに表示し、アプリケーションの 状態に明示的な現在のセグメントを保持してください。
- 同じ空でない
event.activityIdを持つ後続イベントは、現在の行だけをリファイン できます。過去の行を検索せず、キャンペーンIDや素材IDからアクティビティの識別子を 導出しないでください。 - 古いサーバーはnullのアクティビティIDを返すことがあります。素材によるfallbackは、 現在の行の空でない
event.campaign?.materialIdが一致する場合だけ安全です。 - 現在の行の初回観測時刻、位置、その他のUI metadataを保持してください。nativeと Webのreporterは送信metadataを最初の観測に固定するため、アプリケーションも リファイン後のコールバック時刻で置き換えてはいけません。
- 後続イベントにmarkerがない場合やキャンペーンデータが不完全な場合も、最初のmarkerと リファイン後のキャンペーンフィールドを保持します。
- 別の素材の
campaignFoundまたはrecognitionResultイベント、もしくは明示的な認識停止が あればセグメントを閉じます。それ以降に届いた古いアクティビティへの遅延リファインは 無視してください。audioMarkerChangedはセグメントを閉じません。 SORIRecognitionEventType.audioMarkerChangedは独立して観測できるmarker状態です。 このイベントだけでキャンペーンの行を作成またはリファインすることはありません。
A(activity-1) -> A'(activity-1, marker) -> A(activity-1, marker miss)は、 markerを維持する1つの行です。A(activity-1) -> B(activity-2) -> delayed A'(activity-1)ではBが現在のままとなり、履歴上のAは変更されません。
ウィジェットまたはアプリケーションscopeが破棄されるときにsubscriptionをキャンセルします。
await subscription?.cancel();認識の開始と停止
recognizerの設定が完了し、UIがイベントを受け取る準備ができたら、startRecognition()を呼び出します。
await recognizer.startRecognition(
notification: const SORIAndroidNotificationOptions(
title: 'SORI recognition',
body: 'Listening for SORI audio signals',
),
);notificationオプションはAndroidのforeground-service通知で使用されます。iOSとWebでは無視されます。Webでは、ブラウザがマイク権限を要求できるように、ユーザー操作からstartRecognition()を呼び出してください。
認識を停止するには、次を呼び出します。
await recognizer.stopRecognition();現在のrecorder状態も確認できます。
final isRunning = await recognizer.isRecorderRunning();オーディオマーカー認識の有効化
オーディオマーカー認識はデフォルトで無効です。SORI Consoleの設定でオーディオマーカーを使用する場合にのみ有効にしてください。
await recognizer.configure(
config: const SORIRecognitionConfig(audiomarker: true),
);有効にすると、marker-only状態変更はSORIRecognitionEventType.audioMarkerChangedとして配信され、最新のmarkerはevent.audioMarkerから読み取れます。markerを含むキャンペーンが見つかった場合、同じmarkerはevent.campaign?.trait?.markerからも確認できます。
キャンペーンアクションの処理
キャンペーンにaction URLがある場合、まずアプリ側でそのURLを開くかどうかを判断します。アプリがURLを受け入れた後、handleActionUrl()を呼び出すと、SDKを通じてインタラクションがレポートされ処理されます。
final actionUrl = campaign.actionUrl;
if (actionUrl != null && actionUrl.isNotEmpty) {
await recognizer.handleActionUrl(actionUrl);
}認識データベースの更新
SDKは、ネイティブrecognizerにローカル認識データベースの更新をリクエストできます。
updateDatabase()は現在Webではサポートされていません。
final result = await recognizer.updateDatabase();
if (!result.success) {
// result.errorMessageを確認し、必要に応じて再試行オプションを表示します。
}