動画・楽曲・音声・モーション・カメラワーク・トリガー・字幕を、1 本のストリームに。
1 時間のカットシーンでも、ロード待ちもメモリ切れもなく再生できる Unity 6+ 向けライブラリ。
開発状況:音声・動画(HEVC / H.264)・モーション・カメラワーク・トリガー・テキスト・シークは実装済みで、macOS / iOS / Android の実機で再生を検証済みです。Windows はビルドまで確認済みです。
カットシーンやライブ演出を Unity で組むとき、従来は AnimationClip・AudioClip・VideoClip・Timeline がバラバラのアセットで、全部のロード完了を待ち、全データ分のメモリを展開してから再生が始まります。flareStream は動画・音声・モーション・カメラワーク・トリガー・テキストといった異種のタイムドデータを 1 本のストリームファイル (.fst) にインターリーブし、再生ヘッダを読んだ瞬間からプログレッシブに再生を開始します。
ファイル I/O は 1 ハンドル、HTTP 配信ならレンジリクエスト 1 本、暗号化も 1 本のラッパで完結。再生に必要なメモリ量は再生開始前に確定し、再生中の動的確保はありません。
映像と音声が 1 本に入っているから、ダウンロード途中でも、どのプレーヤーでも、すぐ再生が始まる。
先頭を読んだ瞬間に再生が始まり、再生中に必要なメモリは曲の長さに関係なく一定。配信も暗号化もファイル 1 本分で済む。
「音楽・ダンス・カメラ・演出が、決められた時刻どおりに一斉に動く」コンテンツが対象です。
楽曲・ダンス・カメラワーク・ライティングの切り替えを 1 本にまとめて配信。曲を 1 曲追加するたびに増えるファイルは 1 個で、譜面側はトリガーと再生時刻を参照するだけです。
数十分の長尺でも再生中のメモリは増えません。ダウンロードしながら再生を始められるので、「全部落ちるまで待つ」画面が要らなくなります。
収録したモーション・音声・演出トリガーを丸ごと 1 本に保存。後日どの端末で再生しても、同じ演出が同じタイミングで再現されます。
セリフ音声・キャラクターの芝居・カメラ・字幕・エフェクト発火を 1 本に。多言語の字幕や音声は言語ごとのトラックとして同居させられます。
設計の中心に置いている、変わらない 3 つの性質。
ファイル先頭のヘッダを読んだ瞬間に再生を開始でき、必要なメモリ量・総再生時間・トラック構成がその時点で確定します。muxer がインターリーブ窓を保証し、正確なバッファ所要量をヘッダに記録。フルデータをメモリに展開しません。
カットシーンやライブ演出に必要な全データが 1 本に収まります。ロード管理・配信・暗号化の対象がファイル 1 本になり、アセットの取り違えや部分欠けが構造的に起きません。
コンテナはトラックの中身を関知しません。ハプティクスやリップシンクなど任意のタイムドデータを SDK の API でトラックとして追加でき、未知のトラックが混ざったファイルも安全に読み飛ばして再生されます。
異種のタイムドデータを、1 本のストリームの中でサンプル精度で同期。
音声コーデック層には flareOpus を使用し、ロイヤリティフリーの Opus で同等品質の MP3 比 約 1/3〜1/4.6 まで圧縮。libopus のソフトウェアデコードなので全プラットフォームで同じ音が出ます。非圧縮 LPCM も収録でき、複数音声トラックの同時ミックス再生に対応し、全トラックがサンプル精度で同期するため、通常 BGM とアレンジ BGM を音量操作でシームレスに切り替える演出も可能。音声が再生全体のマスタークロックになります。
動画コーデック層には flareVideo を使用し、各 OS 標準のハードウェアデコーダ(VideoToolbox / MediaCodec / Media Foundation)で再生します。iOS / macOS では Metal ゼロコピーでテクスチャに直接届き、B フレーム入りの素材にも対応。負荷が高い端末では遅れたフレームの表示をスキップし、大きく遅れれば次のキーフレームまで読み捨てて全体の同期を守ります(表示・破棄・スキップの統計をデバッグオーバーレイで確認可能)。AV1 / VP9 はフォーマット上の識別子を予約済みで、再生対応は flareVideo の進捗に追従します。
flareMotion は Humanoid ポーズ(マッスル値 95 本 + ルート + ブレンドシェイプ)を、flareCamera はカメラの位置・回転・FOV を、固定レートのサンプル列として収録する標準スキーマです。時刻ベース補間により収録レートと再生 fps は独立で、常に滑らか。全フレームがフルポーズなので任意時刻に即シークでき、遅れた場合も最新フレームだけ適用すれば破綻しません。カーブではなくサンプル列なので、AnimationClip の Keyframe Reduction や誤差許容値(Rotation / Position / Scale Error)をクリップごとに詰める調整は不要で、品質を決めるのは収録レートだけです。再生時はフレームを読んで線形補間するだけなので AnimationClip のカーブ評価より CPU が軽く、データ量は 1 キャラ 30fps・ブレンドシェイプ込みで約 140 kbps、カメラは 1 台約 12 kbps。体格非依存のため異なる体型のキャラクターにもそのまま適用できます。対応リグは Humanoid で、Generic リグは今後対応予定です。
エフェクト発火・シーン切り替え・ライト制御など、任意の瞬時イベントを時刻指定で発火。ペイロードは JSON で、C# イベントとしてメインスレッドで受信。イベント単位の失効時間も設定できます。
字幕・歌詞・キャプションを表示期間付きで時刻どおりに配信(描画はアプリ側で自由に)。多言語は言語ごとに別トラックとして格納し、再生中に API の 1 呼び出しで表示言語を切り替えられます(選んだ言語のトラックだけが配信されます)。
トラックハンドラ登録と muxer のユーザー定義入力で、任意のタイムドデータを追加できます。ハプティクス、リップシンク、照明制御、独自の演出パラメータなど。たとえば「この時刻から 2 秒かけて被写界深度を X から Y へ動かす」という指示を独自トラックに収録し、受け取り側は再生時刻に合わせて補間する、といった使い方ができます。
「再生が始まらない・メモリが読めない」をなくすための機能群。
ヘッダ読了後すぐに再生開始。ストレージの遅いデバイス向けに先読み量 (ReadAhead) を調整可能。必要メモリは Open 時に確定します。
任意時刻へのシークに全トラックが同期して追従。逆方向シークによるスクラブも可能です。インデックスを持つファイル(オーサリング済みの .fst)が対象で、長さ未確定のライブストリームは先頭からの再生のみになります。
CurrentTime を毎フレーム参照でき、輝度変化などトラック化していない任意の演出を再生に同期できます。
トラック別バッファ充填率・スループット・枯渇警告を実機でリアルタイム表示。「なぜ止まったか」を現場で追えます。
すべての非同期 API が CancellationToken / IProgress<float> に対応。シーン遷移でも素直に中断できます。
ロード API は「ファイルパス」「byte[]」「任意の Stream」の 3 系統で、StreamingAssets への平文配置に依存しません。暗号化済み配信はストリーミングのまま復号でき、標準の暗号化オプションも提供予定。
エンコードは ffmpeg やベイクエクスポータなど既存のツールで自由にチューニングし、専用ツール fstmux がタイムスタンプ整列・インターリーブ・メモリ保証の算出を行って .fst 1 本にまとめる 2 段構成です。動画は ffmpeg で作った MP4 から fstmux extract-mp4 で H.264 / HEVC のエレメンタリストリームを取り出して収録し、モーションとカメラは Unity エディタで AnimationClip や Timeline を再生した結果をベイクして flareMotion / flareCamera として書き出します。生成した .fst は ffprobe 相当の fstprobe でトラック構成・コーデックパラメータ・インターリーブ品質・バッファ宣言値を検証でき、fstmux demux / extract-wav / extract-opus / extract-lrc で個別素材に戻せます。Unity エディタ内での .fst 生成(素材ドロップ)にも対応予定。
やらないことも決めています——動画・音声のエンコード機能は持たず、mp4 / mkv / HLS 等の既存コンテナは直接再生せず、字幕の描画や DRM の鍵管理は扱いません。コンテナと同期再生に集中する設計です。
.fst はブラックボックスではありません。付属の CLI fstprobe は、ヘッダに書かれた宣言値(平均レート・最大チャンク・バッファ量)と全チャンクを走査した実測値を並べて表示し、タイムスタンプの順序・インターリーブ窓の制約・宣言値と実測値の一致・Index の整合性を検証します。問題があれば「症状 + 対処」を 1 行で示し、終了コードで結果を返します。下はベンチマークと同じ Candy Rock Star の .fst に掛けた実際の出力(抜粋)。ベンチマークの「再生時メモリ 19.2 KiB」は、ここに出ている min buffer の値そのものです。
$ fstprobe crs.fst Format container: flareStream .fst v0.1 file size: 8,900,620 bytes (header 7,333 / body 8,420,781 / index 472,490 / footer 16) duration: 240.667 s bitrate: 295,865 bit/s interleave window: 500.0 ms index: 26,249 entries tracks: 5 min buffer: 19,692 bytes (Σ buffer_size_hint) Track #0 audi/opus MustPlay codec: 48000 Hz 2 ch, pre_skip=312, input 48000 Hz declared: avg 15,226 B/s, max_chunk 636 bytes, buffer_size_hint 9,956 bytes measured: avg 15,226 B/s, max_chunk 636 bytes, buffer peak 9,956 bytes chunks: 11,752 (RAP 11,752 / discontinuity 0 / EOS 0), payload 3,664,271 bytes time: 0.000 s .. 235.020 s, avg interval 20.0 ms Track #1 motn/fmo0 LatestWins codec: flareMotion v0 "unitychan" 30 fps, 7221 frames, 95 muscles, 31 blend shapes declared: avg 16,803 B/s, max_chunk 560 bytes, buffer_size_hint 8,960 bytes measured: avg 16,803 B/s, max_chunk 560 bytes, buffer peak 8,960 bytes chunks: 7,221 (RAP 7,221 / discontinuity 0 / EOS 0), payload 4,043,760 bytes time: 0.000 s .. 240.667 s, avg interval 33.3 ms Track #2 motn/fcam, #3 trig/trgj, #4 text/txtj ... (略) Problems 問題は見つかりませんでした。
--json でビルドパイプラインから読める形に、--strict で警告も終了コード 2 に格上げして CI の品質ゲートに、--header-only で巨大ファイルのヘッダだけを素早く確認、--chunks / --index でチャンクや Index の一覧に降りられます。macOS(Apple Silicon / Intel)と Windows 向けの単体バイナリで、.NET ランタイムのインストールは不要です。
従来構成(モーションと音声を個別アセットとして読み込む組み方)と flareStream を、同一コンテンツで実測比較しました。題材は Unity-chan「Candy Rock Star」の約 4 分のライブ演出(楽曲 235.0 秒 / ダンス 240.7 秒)です。
計測環境は Unity 6000.3.23f1 / macOS (Apple Silicon)、メモリは Profiler.GetRuntimeMemorySizeLong() によるアセット実体のランタイムサイズ。キャラクターモデル(メッシュ・テクスチャ)はどちらの方式でも同じだけ必要なため、比較対象から除いています。
macOS (Apple Silicon) での実測。従来構成の斜線部分はモーション (AnimationClip 45 MiB) の展開時間で、音声とは別に加算されますが今回は未計測です。
バーの長さは指標ごとに従来構成を同じ長さに揃えた相対表示。ほかに、モーション適用コストは 1 フレームあたり 0.02 ms(95 マッスル + ブレンドシェイプ 31 件、flareStream 実測)。
| 指標 | 測り方 | 従来構成 | flareStream |
|---|---|---|---|
|
再生時メモリ(時系列データ)
|
従来は AnimationClip 45.27 MiB + AudioClip 39.55 MiB の全展開。flareStream はコンテナが宣言するバッファ量の合計 | 84.8 MiB | 19.2 KiB |
|
再生開始までの時間
|
従来は音声の LoadAudioData だけで 493 ms(モーションの展開は別途)。flareStream はヘッダ読了までの時間 |
493 ms + | 32 ms |
|
データサイズ
|
従来は FBX 7.01 MiB + mp3 7.25 MiB。flareStream はカメラワークと字幕も含んだ .fst 1 本 | 14.26 MiB | 8.49 MiB |
|
ファイル数・I/O ハンドル数
|
従来は FBX / 音声 / 演出スクリプト / シーンに分散。HTTP 配信ならリクエスト本数も同数 | 4 種以上 | 1 個 |
|
モーション適用コスト
|
95 マッスル + ブレンドシェイプ 31 件の適用(flareStream 実測) | — | 0.02 ms |
従来構成の音声を Streaming 設定にすれば、音声分のメモリは削減できます。ただし AnimationClip にストリーミング再生の仕組みは存在しないため、モーションの 45 MiB は展開されたままです。この点が構造的な差になります。
数値の背景にある設計判断と、それが開くこと。
バッファ量は「インターリーブ窓」という時間幅で決まるため、4 分でも 1 時間でも再生時メモリは変わりません。muxer が各トラックの最大バッファ占有量をファイルに記録し、再生側はヘッダを読んだ時点で所要量を確定できます。
Unity の AnimationClip にはストリーミング再生の仕組みがありません。flareStream はモーションをタイムスタンプ付きチャンク列として持つため、音声と同じように「必要な区間だけ読む」再生ができます。
モーションは「任意時刻のポーズを返すもの」として扱い、描画フレームごとに時刻ベースで補間します。30fps で収録したモーションを 60fps でも 120fps でも可変フレームレートでも滑らかに再生でき、24fps 動画と 60fps モーションの混在も問題になりません。
Humanoid のマッスル値は体格で正規化された値なので、収録元と異なる体型のキャラクターにそのまま適用できます。リターゲット処理は不要です。
アニメーションデータとして存在しない演出、たとえば実行時にコードで生成されるカメラワークも、同じロジックを決定的に回して時系列サンプルとして収録できます。ベンチマークに使ったサンプルのカメラワークが実際にそれで、毎回まったく同じ演出を再現できるようになります。配信・収録コンテンツで効いてくる性質です。
コンテナはトラックの中身を関知しないので、被写界深度の遷移・ハプティクス・照明制御といった独自の時系列データを、独自トラックとして同じストリームに同居させられます。受け取り側はハンドラを 1 つ登録するだけで、提示時刻どおりに届きます。
同じ .fst・同じサンプルシーンを、各プラットフォームの実機で再生して確認しています。題材はベンチマークと同じ Unity-chan「Candy Rock Star」約 4 分(楽曲 + ダンス + カメラワーク + 演出トリガー + 歌詞字幕を 1 本の .fst に収録)です。
| プラットフォーム | 検証機 | フレームレート | モーション適用 | 結果 |
|---|---|---|---|---|
macOS |
Apple Silicon Mac | 60 fps | — | 音声の途切れなし。Unity 合計メモリ 80.1 MB |
iOS |
iPhone 17 / iOS 26.6.1 | — | — | 5 トラック 235 秒を通しで再生。モーション・カメラ・トリガー・字幕すべて同期、例外なし(フレームレートは未計測) |
Android |
Pixel 5a / Android 11 | 30 fps | 0.11 ms | 音声の途切れなし。Unity 合計メモリ 80.9 MB |
Windows |
— | — | — | ビルドまで確認済み(実機での再生確認は準備中) |
実機でのバッファ実測(Android)は音声 195 KB・モーション 16.4 KB・カメラ 1.2 KB(macOS は 195 KB / 18.6 KB / 1.3 KB)。コンテンツの長さに関係なく一定で、再生が進んでも増えません。動画込みのデモ(720p H.264 + Opus)も macOS / iOS / Android の実機で再生を確認しており、iOS / macOS は Metal ゼロコピー、Android は Unity 合計メモリ 67 MB で動作します。実機の .fst はアプリ専用領域に配置して読み込んでおり、StreamingAssets への平文配置に依存しません。
「軽い・速い」だけでなく、データが劣化していないことを検証で担保しています。すべて自動テストとして常設し、変更のたびに実行しています。
| 検証項目 | 内容 | 結果 |
|---|---|---|
音声(Opus 往復) |
WAV → Opus 96 kbps → .fst → デコードの往復で SNR を測定 | 42.31 dB |
音声(非圧縮 往復) |
WAV → .fst → デコードでバイト列を比較 | 完全一致 |
モーション往復 |
ベイク → .fst → 適用で 95 マッスルと重心 TRS を比較 | 誤差 < 0.005 |
コンテナ往復 |
エレメンタリストリーム → mux → demux でバイト列を比較 | 完全一致 |
muxer は決定的です(同一入力から常にバイト一致の .fst を生成)。付属の fstmux demux で .fst を個別トラックに戻せ、fstprobe で宣言値と実測値の一致やインターリーブ窓の制約を検証できるため、往復検証はご自身の環境でも再現できます。上記に加え、コンテナ層と muxer の自動テスト 316 件、Unity エディタ上の自動テスト 49 件を常設し、変更のたびに実行しています。
音声コーデック層には flareOpus、動画コーデック層には flareVideo を使用します。コンテナ・モーション・カメラ・トリガー・テキストは C# のみで実装されているため Unity が動く環境ならそのまま動作し、音声 Opus のネイティブプラグインは iOS / Android / macOS / Windows に対応済みです。動画トラックは flareVideo のネイティブプラグインを使い、macOS / iOS / Android で再生を確認済み、Windows は flareVideo の対応に追従します。コンソール対応はアドオンとして検討中です。
有償ライセンスでの提供を予定しています。フォーマットのコア仕様と実装は一般には公開していませんが、採用いただくプロジェクトには仕様書とソースコードを開示する予定です。ご相談・ユースケースのご連絡は [email protected] までお寄せください。