Cocos Creator セッションリプレイ(実験的)¶
本ドキュメントでは、Cocos Creator Session Replay の初期化、Camera 選択、パフォーマンスパラメータ、タッチプライバシー、ノードプライバシーのルールについて説明します。
実験的機能
Cocos Creator セッションリプレイは現在実験的な機能であり、API、プラットフォーム互換性、リプレイ品質は今後のバージョンで変更される可能性があります。本番環境で使用するかどうかを判断する前に、まずテスト環境でプライバシー、パフォーマンス、リプレイの完全性を評価することをお勧めします。
前提条件¶
Session Replay の前提条件:
- Android または iOS のネイティブビルド
- RUM が初期化済みであること
- 有効な RUM View が存在すること
- 現在の SDK バージョン構成に記載された Cocos SDK とネイティブ依存関係を使用していること
有効な RUM Context がない場合、SDK は現在のフレームをスキップし、RUM とは独立したリプレイデータを生成しません。autoTrack.scenes を有効にするか、フレームキャプチャの前に guanceSdk.rum.startView() を手動で呼び出すことをお勧めします。
独立 Replay パッケージのインストール¶
Cocos SDK 0.1.0-alpha.6 以降、セッションリプレイは @cloudcare/cocos-session-replay によって個別に提供されます。Cocos プロジェクトのルートディレクトリに、完全に同じバージョンの 2 つのパッケージをインストールしてください:
npm install @cloudcare/cocos-sdk@0.1.0-alpha.6 @cloudcare/cocos-session-replay@0.1.0-alpha.6
npx --no-install guance-cocos install --project . --replay
Creator を開き直し、ネイティブプロジェクトを生成してコンパイルします。CocoaPods を使用する iOS プロジェクトでは pod install も実行する必要があります。SPM の設定とスイッチの保持ルールについては、アプリ導入を参照してください。
基本パッケージには、Replay API、フレームキャプチャの実装、Replay のネイティブ依存関係は含まれません。以下の例では、合成後のインスタンスを observability.ts でエクスポートされる guanceSdk として保存し、他のモジュールはこのインスタンスを再利用します。
初期化¶
説明
このページのコード例における ... は、sdk の基本設定(例: datakitUrl)が省略されていることを示します。先に SDK 初期化 を参照して共通設定を完了してください。このページでは Session Replay 関連の設定のみを説明します。
import { guanceSdk as baseSdk } from '@cloudcare/cocos-sdk/creator3';
import { withSessionReplay } from '@cloudcare/cocos-session-replay/creator3';
export const guanceSdk = withSessionReplay(baseSdk);
guanceSdk.start({
...,
rum: {
androidAppId: 'android-rum-app-id',
iosAppId: 'ios-rum-app-id',
},
replay: {
sampleRate: 1,
sessionOnErrorSampleRate: 0,
captureFps: 2,
maxImageDimension: 720,
imagePolicy: {
quality: 'medium',
},
touchPrivacy: 'show',
},
autoTrack: {
scenes: true,
},
});
Creator 2 の場合は、両パッケージのインポート入口を /creator2 に変更してください。合成は SDK 初期化または Hybrid attach() の前に行う必要があります。以降の .replay、start({ replay })、attach({ replay }) はすべて合成後のインスタンスで呼び出します。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
sampleRate |
number |
いいえ | Session Replay セッションのサンプリングレート。範囲 0–1 |
sessionOnErrorSampleRate |
number |
いいえ | エラーセッションの補完サンプリングレート。範囲 0–1 |
captureFps |
number |
いいえ | 1 秒あたりのフレームキャプチャ数。整数 1–5 のみ許可。デフォルトは 1 |
maxImageDimension |
number |
いいえ | キャプチャ画像の長辺のピクセル数。範囲 1–2048。デフォルトは 720 |
imagePolicy |
FTReplayImagePolicy |
いいえ | 画像のエンコード、単一フレームサイズ、1 分あたりのトラフィックポリシー。明示的に指定すると画像トラフィック制御が有効になります |
touchPrivacy |
show / hide |
いいえ | タッチデータのプライバシーレベル。show はタッチの押下位置と離した位置を記録し、hide はタッチ位置を記録しません。デフォルトは hide |
不正なサンプリングレート、FPS、画像サイズ、またはトラフィックポリシーが指定された場合、TypeScript 層で TypeError または RangeError がスローされます。
画像トラフィックポリシー¶
imagePolicy は、録画済みセッションで生成される画像 Resource のトラフィックを制限するために使用します。品質レベルを設定するだけで、対応するプリセットが適用されます:
| レベル | デフォルトの長辺 | エンコード品質 | 通常の単一フレーム上限 | 画像 Resource のスライディング 60 秒予算 |
|---|---|---|---|---|
low |
480 px | 0.35 | 20 KiB | 0.6 MiB |
medium |
720 px | 0.45 | 40 KiB | 1.5 MiB |
high |
960 px | 0.60 | 80 KiB | 4 MiB |
imagePolicy では以下のフィールドを指定できます:
| フィールド | 型 | デフォルト値 | 説明 |
|---|---|---|---|
quality |
low / medium / high |
medium |
品質プリセット。captureFps は変更しません |
maxFrameBytes |
number |
現在のレベルのプリセット | 通常の画像 Resource の最大エンコードサイズ。範囲 1 KiB–1 MiB |
maxBytesPerMinute |
number |
現在のレベルのプリセット | 画像 Resource のスライディング 60 秒予算。範囲 16 KiB–64 MiB。maxFrameBytes 以上である必要があります |
adaptiveCapture |
boolean |
true |
予算の使用量に応じて、有効な画像出力頻度、品質、サイズを適応的に下げるかどうか |
明示的に設定した maxImageDimension、maxFrameBytes、maxBytesPerMinute は、レベルのプリセットを上書きします。captureFps は常に独立して設定されます。2 fps 以上に上げた場合、予算コントローラーが実際の出力を制限するため、トラフィックは公称 FPS に応じて線形に増加し続けることはありません。
adaptiveCapture を有効にすると、SDK は直近 60 秒間に受け入れられた画像サイズに基づいて収集を調整します:
| 予算の使用量 | 動作 |
|---|---|
| 75% 未満 | 設定された captureFps、品質、サイズでキャプチャ |
| 75% に達した | 有効な画像出力頻度が約 0.5 fps に低下 |
| 90% に達した | 出力頻度の低下に加えて、エンコード品質と画像サイズをさらに低下 |
| 100% に達した | スライディングウィンドウが予算を解放するまで画像 readback を一時停止。書き込み待ちのタッチ記録は引き続き保存 |
新しい View または画面の縦横切り替えの最初のフレームでは、最大 100 KiB の独立したバースト枠を使用でき、ページ切り替え後にできるだけ早く完全な画面が表示されることを保証します。品質が頻繁に変動するのを防ぐため、予算が低下した後は低い復帰しきい値を使用して、通常のキャプチャ状態に段階的に戻ります。
iOS では JPEG、Android では WebP でエンコードされ、実際のエンコードサイズに基づいて単一フレームの上限と分単位の予算が計算されます。エンコード結果が maxFrameBytes を超える場合は、まず品質を下げ、次にサイズを縮小します。それでも上限を超える場合は Resource に書き込みません。
Camera の選択¶
デフォルトでは、現在のシーンで見つかった最初の Camera が使用されます。複数の Camera を使用するプロジェクトでは、リプレイ対象の Camera を明示的に指定してください:
import { guanceSdk } from './observability';
export function selectReplayCamera(camera: unknown): void {
guanceSdk.setReplayCamera(camera);
}
setReplayCamera() は一度に 1 つの Camera のみを保存します。複数回呼び出した場合、最後に渡された Camera が以前の設定を上書きし、SDK は複数の Camera を同時にキャプチャまたは合成しません。呼び出し時に前のフレームがキャプチャ中だった場合、新しい Camera は次回のキャプチャから有効になります。
メインの Camera を切り替えた後は、setReplayCamera() を再度呼び出す必要があります。シーン内に利用可能な Camera がない場合、現在のフレームはスキップされます。
タッチプライバシー¶
touchPrivacy は、Session Replay がタッチ位置を記録するかどうかを制御します:
| モード | 動作 |
|---|---|
show |
Replay でタッチの押下位置と離した位置を記録 |
hide |
タッチ位置を記録しない。デフォルト値 |
タッチの収集は Session Replay に属し、autoTrack.actions とは独立しています。autoTrack.actions を有効にしていなくても、touchPrivacy: 'show' を設定すると Replay にタッチが記録されます。逆に、Action の自動収集を有効にしていても touchPrivacy: 'hide' のままの場合、Replay にタッチ位置は表示されません。前後のフレームで画面に変化がなくても、書き込み待ちのタッチ操作は Replay に個別に保存されます。
現在の Cocos API はグローバルなタッチプライバシー設定のみをサポートしており、ノード単位でのタッチプライバシーの上書きには対応していません。guanceSdk.replay.setPrivacy(node, 'hide') はノードの画面を非表示にするだけで、その位置のタッチ記録は非表示になりません。機密ページでは、Session Replay の開始時に touchPrivacy: 'hide' を使用してください。
タッチ位置のプライバシー
タッチ座標によって、ユーザーが機密ページで行った操作の位置が明らかになる可能性があります。プライバシー評価を完了し、必要な承認を得た場合にのみ show に設定してください。それ以外の場合はデフォルトの hide を維持してください。
ノードプライバシー¶
すべての EditBox ノードはデフォルトで mask が適用されます。特定のノードにルールを設定することもできます:
guanceSdk.replay.setPrivacy(accountNode, 'mask');
guanceSdk.replay.setPrivacy(secretPanelNode, 'hide');
guanceSdk.replay.setPrivacy(publicNode, 'unmask');
| モード | 動作 |
|---|---|
mask |
マスク色でノードの矩形領域を覆う |
hide |
単色でノードの矩形領域を非表示にする |
unmask |
そのノードのカスタムルールを削除する |
unmask はカスタムルールのみを削除します。ノードが引き続き EditBox である場合、デフォルトのマスクは引き続き有効です。
プライバシー領域は、ノードのワールド座標の矩形に基づいて計算されます。カスタムレンダリング、パーティクル、Shader、RenderTexture、またはノードのバウンディングボックスを超える視覚コンテンツは、プライバシー領域が自動的に導出されないため、導入テストでシーンごとに確認する必要があります。
ページ単位でのマスク管理¶
setPrivacy() のルールは、渡されたノードのインスタンスにバインドされ、ページ名や RUM View に応じて自動的に切り替わりません。ページごとに異なる内容をマスクする必要がある場合は、各ページの進入・離脱ロジックで各ノードのルールを管理してください。
以下では、同じシーン内で「診断ページ」と「操作ページ」を切り替える例を示します。diagnosticsPage と motionPage は 2 つのページのルートノードで、privateTokenNode は診断ページ内でマスクが必要な通常のノードです。SDK の初期化または Hybrid attach() の完了後、ページ切り替え時に以下の関数を呼び出します:
function showDiagnostics() {
// ページに入るたびに再設定し、機密ノードが表示される前にマスクルールが適用されるようにします。
guanceSdk.replay.setPrivacy(privateTokenNode, 'mask');
motionPage.active = false;
diagnosticsPage.active = true;
}
function showMotion() {
// 先に機密ページを非表示にしてから、そのページのノードのカスタムルールを削除します。
diagnosticsPage.active = false;
guanceSdk.replay.setPrivacy(privateTokenNode, 'unmask');
motionPage.active = true;
}
操作ページにも機密ノードがある場合は、表示前に各ノードに mask または hide を設定し、離脱時に対応するルールを削除してください。1 つのページに複数のカスタムマスクノードがある場合は、1 つずつ管理する必要があります。
ページのライフサイクルでは、以下の点にも注意してください:
- ページまたは親ノードを
active = falseに設定するだけでは、登録済みのカスタムルールは削除されません。ページを非表示にしてもunmaskの呼び出しの代わりにはならないため、古いページのマスク領域が後続の画面に影響を与える可能性があります。 - ページを離れる前、またはノードが破棄される前に、そのページで登録したカスタムルールを削除してください。ロジックはプロジェクトのページマネージャーや、コンポーネントの有効化・無効化・破棄のコールバックに配置できます。
- ページに再度入る場合はルールを再設定してください。ページが破棄されて再構築された場合は、新しく作成したノードのインスタンスを渡す必要があります。
- RUM View の名前を切り替えても、ノードのルールは自動的に設定または削除されません。Hybrid の
enterCocos()/leaveCocos()は収集の帰属を管理しますが、ページのノードマスクは引き続き各ページで管理する必要があります。 unmaskは指定したノードのカスタムルールのみを削除します。グローバルなプライバシー保護は無効になりませんし、EditBoxのデフォルトマスクも解除されません。
これらのルールは、Cocos のフレームキャプチャにおけるノードの画面に影響します。Hybrid のネイティブページでは、引き続きホスト Native SDK の Session Replay プライバシー設定が使用され、タッチ位置は touchPrivacy によって個別に制御されます。
検証時は「ページに入る → 他のページに切り替える → 再度入る」の一連の流れをカバーし、Replay で機密コンテンツが継続的にマスクされていること、他のページにマスクが残っていないことを確認してください。
プライバシーに関するさらなる推奨事項については、データとプライバシーを参照してください。
実行時の動作¶
- Cocos の
RenderTextureを使用して RGBA 画面をキャプチャします。 imagePolicyを設定していない場合は従来の画像パスが維持されます。明示的に設定すると、Android では WebP V2、iOS では JPEG V2 が使用され、実際のエンコードサイズに基づいて消費量が記録されます。- プライバシーマスクは画像の圧縮前に適用されます。
- 内容が完全に同一またはほぼ静止しているフレームはスキップされます。View、画面サイズ、またはプライバシールールに変化があった場合は、変化フレームが強制的に生成されます。
- 画像が重複排除、予算、またはエンコードサイズの理由でスキップされた場合でも、書き込み待ちのタッチ記録は個別に保存されます。
- 前のフレームが処理中の場合、新しいフレームは並行して処理されません。
- 単一フレームのキャプチャまたはエンコードに失敗した場合は、現在のフレームのみが破棄され、以降の Session Replay の収集は停止しません。
- 一時画像は Native SDK に書き込まれた後、アプリの一時ディレクトリから削除されます。
トラフィックの見積もり¶
トラフィック予算は画像 Resource のみを対象としており、Replay Segment、タッチ記録、アップロードプロトコルのオーバーヘッドは含まれません。連続したバトル、カメラ移動、パーティクルなどの高ダイナミクス画面は、通常レベル上限に近くなります。メニュー、静的背景、少量の UI アニメーションは、完全同一フレームとほぼ静止の検出の影響を受けるため、実際の消費量は通常より低くなります。
以下の表は、V2 エンコードと対応するレベルのデフォルト設定に基づき、単一の安定した View を想定した見積もりです。キャパシティプランニング用であり、実測データやネットワーク課金の保証ではありません。maxImageDimension、maxFrameBytes、maxBytesPerMinute を明示的に変更すると、範囲と上限もそれに応じて変わります。
| レベル | カジュアルシーンの画像トラフィック見積もり | 高ダイナミクスシーンの画像 Resource 上限 | タッチ頻度が低い場合の高ダイナミクス総量の参考値 |
|---|---|---|---|
low |
0.1–0.4 MiB/分 | 0.6 MiB/分 | 約 0.7–0.9 MiB/分 |
medium |
0.2–0.8 MiB/分 | 1.5 MiB/分 | 約 1.6–1.8 MiB/分 |
high |
0.4–1.6 MiB/分 | 4 MiB/分 | 約 4.1–4.4 MiB/分 |
カジュアルシーンの範囲は、画面に継続的に小さな変化があることを想定しています。画面が完全に静止している場合、重複排除後のトラフィックはさらに低くなる可能性があります。高ダイナミクスの画像値はスライディング 60 秒予算の上限であり、固定の消費量ではありません。総量の参考値は、画像 Resource に加えて、タッチ頻度が低い場合の Replay Segment、タッチメタデータ、アプリケーション層のアップロードオーバーヘッドを見積もったものであり、本番ネットワークにおける TLS、TCP/IP、セルラー、Wi-Fi リンクのオーバーヘッドは含まれません。
Android V2 は WebP、iOS V2 は JPEG を使用します。画像コンテンツ、圧縮処理のプラットフォーム差異、実際の変化フレーム数、View や画面方向の切り替え回数、タッチ頻度、アップロードの再試行はすべて最終的なトラフィックに影響します。リリース前に、対象プラットフォームと実際のビジネスシーンで測定してください。
録画済みの単一セッションの画像トラフィックは、以下の方法で見積もることができます:
例えば、captureFps: 2、quality: 'medium' の場合、ダイナミックな画面では予算が 75% に達すると出力頻度が自動的に下がり、90% に達すると品質とサイズが低下します。画像 Resource は 1.5 MiB のスライディング 60 秒予算に制約され、2 × 60 × 40 KiB で約 4.7 MiB/分まで増加し続けるわけではありません。新しい View または画面方向の切り替え時の最初のフレームでは、最大 100 KiB の独立したバースト枠を使用できるため、該当する期間は通常の画像予算を一時的に上回る可能性があります。
予算は録画済みの各セッションを対象としており、セッションのサンプリングの代わりにはなりません。本番環境では、まず通常セッションの sampleRate を 0.01–0.05 に設定し、トラブルシューティングのニーズに応じて sessionOnErrorSampleRate を設定してください。診断環境では一時的に 100% サンプリングを使用できます。全体の画像トラフィックは以下の方法で見積もることができます。エラーセッションの補完サンプリング、Segment、ネットワークプロトコルのオーバーヘッドは別途計算する必要があります:
一体型パッケージからの移行¶
0.1.0-alpha.5 以前のバージョンからアップグレードする場合:
- 基本パッケージを
0.1.0-alpha.6にアップグレードし、同じバージョンの Replay パッケージをインストールして、インストーラー--replayを再実行します。 - 最初の
start()/attach()の前にwithSessionReplay(baseSdk)を呼び出し、ビジネスコードが合成後のインスタンスを再利用できるようにします。 - 従来は独立してエクスポートされていた
setReplayCamera(camera)を、guanceSdk.setReplayCamera(camera)に変更します。 FTSessionReplayConfig、FTHybridSessionReplayConfig、FTReplayImagePolicyなどの Replay 型のインポートを、@cloudcare/cocos-session-replay/creator2または/creator3に移動します。Replay を含む全体設定には、それぞれFTCocosReplayConfigとFTCocosHybridReplayConfigを使用します。- ネイティブプロジェクトを再生成してコンパイルします。JavaScript を置き換えるだけでは新しい Replay Bridge はインストールされません。
Replay を今後使用しない場合は、合成と Replay 設定を削除し、インストーラー --no-replay を実行して再ビルドします。このスイッチは、インストーラーが管理するネイティブ統合を削除するためのものです。実行時にフレームキャプチャを一時停止する場合は、後述の replay.stop() を使用し、Hybrid シナリオでは leaveCocos() を使用します。
開始と停止¶
Replay パッケージをインストールして合成していることを前提に、guanceSdk.start() で replay を渡していない場合でも、RUM の初期化と View の開始後に個別に開始できます:
guanceSdk.replay.start({
sampleRate: 1,
captureFps: 1,
maxImageDimension: 720,
touchPrivacy: 'show',
});
フレームキャプチャを停止します:
guanceSdk.shutdown() でもフレームキャプチャは停止します。guanceSdk.start({ replay: ... }) と guanceSdk.replay.start() を同時に使用して二重に開始しないでください。
ネイティブホストの Hybrid モードでは、上記の開始・停止インターフェースは使用されません。Session Replay はネイティブホストによってネイティブ recorder モードで初期化され、Cocos は enterCocos() と leaveCocos() の間、自動的に外部キャプチャソースに切り替わります。詳細はネイティブホスト Hybrid 導入を参照してください。
パフォーマンスの推奨事項¶
captureFps: 1、imagePolicy: { quality: 'medium' }から検証を開始し、より滑らかな画面が必要な場合に2 fpsに引き上げてください。- リプレイが必要なビジネス環境でのみサンプリングを有効にしてください。
- 低スペック端末で GPU、メモリ、またはディスクに負荷がかかる場合は、まず
lowに変更し、次に長辺のサイズとサンプリングレートを下げてください。 - 画面の縦横切り替え、複数の Camera、複雑な UI、低フレームレートのシーンで、画像の向きとマスクの位置を検証してください。