Music Understanding入門:オンデバイスのオーディオ解析
WWDC 2026で、AppleのFinal Cut Proチームは単一のフレームワーク上に構築された2つの機能を発表しました。1つは楽曲のビートグリッドを可視化し、編集者がカットを小節やビートに合わせられるビート検出機能、もう1つはクリップを音楽に自動同期させるiPad向けのモンタージュ機能です。1 どちらも新しいフレームワークMusic Understandingの上で動作します。このフレームワークは、信号処理や機械学習の知識を一切必要とせずに、楽曲の音楽的インテリジェンス(キー、リズム、構造、ペース、楽器の動き、ラウドネス)を提供します。すべてオンデバイスで実行されるため、解析するオーディオはプライバシーが守られ、オフラインでも動作します。1 この記事では、フレームワークをビルドしながら追っていきます。6つの解析領域、MusicUnderstandingSessionがそれらをどのように生成するか、そしてオーディオに反応するビジュアルを実用化するストリーミングラウドネスのAsyncSequenceを見ていきましょう。
TL;DR
- Music Understandingは楽曲の6つの領域(キー、リズム、構造、ペース、楽器の動き、ラウドネス)をオンデバイスで解析し、信号処理や機械学習の専門知識を必要としません。1
AVAssetまたはカスタムオーディオプロバイダーからMusicUnderstandingSessionを作成し、すべてを取得するにはanalyze()を、特定の型だけを対象として不要な計算を省くにはanalyze(for:)を呼び出します。1- 結果は
SessionResult構造体に届き、各特徴量はオプショナルなフィールドとして表現されます。汎用のanalyze()はそのすべてを埋め、対象を絞ったanalyze(for:)は残りをnilのままにします。1 - 時間を扱う2つの型がAPI全体を貫いています。
TimedValueは値をCMTimeと組み合わせ、RangedValueは値をCMTimeRangeと組み合わせます。1 MusicUnderstandingSessionは、解析したオーディオ100msごとにAsyncSequenceで値を届けるストリーミングラウドネスAPIも公開しています。これがライブのオーディオリアクティブなアニメーションを駆動する基盤となります。1
オンデバイスの音楽的インテリジェンスが重要な理由
AppleのComputational Music TeamのConnerが、1:39からフレームワークの6つの解析領域を紹介しています。
その狙いは控えめで正直です。このフレームワークは「信号処理とモデル推論をすべて代わりに処理してくれるため、利用にあたって信号処理や機械学習の専門知識は一切必要ありません」。1 これにより、オーディオ解析のうち多くのアプリ開発者が決して抱えたくなかった部分が取り除かれます。テンポを検出する、楽曲をコーラスとバースに分割する、知覚されるラウドネスを測定する——いずれもかつては、サードパーティのエンジンをライセンスするか、DSPパイプラインを手作業で構築するかを意味していました。
オンデバイスで実行することは、プライバシーの計算も変えます。フレームワークは「完全にオンデバイスで実行されるため、解析するオーディオはプライバシーが守られ、オフラインでも動作する」からです。1 楽曲が解析のために端末を離れることはなく、電波のない飛行機の中でも解析が機能します。ライブラリをテンポで並べ替えるDJアプリや、カットをビートに合わせるビデオエディタにとって、ネットワーク依存がなく、オーディオが端末の外に出ないというこの組み合わせこそが、実用上の鍵となります。
Appleはこの6つの領域を楽曲の構成要素として説明しています。リズムは脈拍であり、個々のビートに駆動されて小節へと積み上がります。1分間のビート数がbeats per minute、すなわちbpmです。1 小節はフレーズ(音楽的な文)を形作り、フレーズが組み合わさってセグメントとなり、セグメントがコーラス、バース、イントロ、ブリッジといったセクションを構築します。1 ドラム、ベース、ボーカルといった楽器は、キーと呼ばれる共通の音の集まりを中心に、それぞれ異なるタイミングと強さで演奏されます。1 楽曲はbpmを一定に保ちながらも、部分によって遅く感じたり速く感じたりすることがあり、Appleはこれをペースと呼びます。そして楽曲は、ある箇所では他より大きく鳴ります。1 これら6つの概念は、フレームワークの結果型と一対一で対応しています。
セッション:1つのオブジェクト、2通りの問い方
アプリはMusicUnderstandingSessionとやり取りし、それを「AVAssetまたはカスタムオーディオプロバイダーのいずれか」で初期化します。1 解析を実行するには、analyzeを呼び出して結果を待ちます。デフォルトの動作はすべての型を解析することですが、Appleはパフォーマンスのレバーを明確に示しています。「最高のパフォーマンスを得るには、関心のある解析型を指定することで、不要な計算を避けられます」。1 描画するものだけを計算するかどうかが、応答性の高いツールと、読み込みのたびに重くなるツールとの違いを生みます。
サンプルアプリのMusic Understanding Labは、ファイルのパスを端から端まで示しています。SwiftUIのfileImporterが楽曲を選択してそのURLを返し、そのURLがAVURLAssetになります。Appleは1つの設定が重要だと指摘しています。「最も正確な結果を保証するために」PreferPreciseDurationAndTimingKeyをtrueに設定してください。1 その後、アセットからセッションを作成し、analyzeを呼び出してセッション結果が返るのを待ちます。
それらの結果はSessionResult構造体に届きます。そこでは「Music Understandingが解析するすべての特徴量が、それぞれ独自の結果フィールドを持ちます。これらはすべてオプショナルです」。1 2つのエントリーポイントは、何を埋めるかが異なります。汎用のanalyze() APIはすべての結果を利用可能にします。対象を絞ったanalyze(for:) APIは要求した結果だけを返し、「残りはnilになります」。1 つまりオプショナルであることは、API設計上の偶然ではありません。フレームワークが実際にどの処理を行ったかを伝える手段なのです。
値に時間を付加するために、2つの型がフレームワーク全体に繰り返し登場します。TimedValueは値をCMTime(単一の瞬間)と関連付け、RangedValueはCMTimeRange(一定の幅)を値と関連付けます。1 以下のほぼすべての結果はこの2つの形のいずれかで表現されるため、一度学んでおけば6つの領域すべてで役立ちます。
6つの結果を歩く
キー。 キー解析では、フレームワークはKeyResult構造体を返します。これは「RangedValueを使ってKeySignatureを特定の時間範囲に対応付ける、範囲の配列を含みます」。1 KeySignatureはトニックとモードを保持します。トニックは「標準的なクロマティックピッチのいずれか」であり、楽曲が中心とする根音(CやGなど)を表します。モードは「メジャーかマイナーのいずれか」です。1 結果が単一の値ではなく範囲の配列であるため、このAPIは途中でキーが変わる楽曲にも対応できます。
リズム。 リズムを解析するとRhythmResultが得られます。この構造体は「すべてのビートと小節のタイムスタンプをCMTimeの配列として」提供し、加えてbeatsPerMinuteを通じて全体のグローバルなテンポを示します。1 ライブUIにとって重要な細部が1つあります。beatsPerMinuteはオプショナルです。「フレームワークが少なくとも2つのビートを見つけるのに十分なオーディオをまだ処理していない場合、bpmはnilに設定される」からです。1 間隔を測るには2つのビートが必要であり、このnilはフレームワークが推測を拒んでいることを意味します。
構造。 構造解析を要求すると、3つのプロパティを持つStructureResultが返ります。「セクション、セグメント、フレーズ」のためのもので、それぞれについてCMTimeRangeの配列が得られます。1 この3つのレベルは入れ子になっています。セクションは1つ以上のセグメントで構成され、各セグメントはフレーズで構成されます。1 この階層こそが、編集者が任意のタイムスタンプではなくコーラスの境界にカットをスナップできる理由です。
ペース。 ペースは「音楽が聴き手にどれだけ速く感じられるかを示し」、よりエネルギッシュな部分は遅い部分より高い値を持ちます。1 これを要求するとPaceResultが返ります。これは「範囲付きの値の配列を含む単一のプロパティ」を持つ構造体です。1 ペースはbpmとは異なります。テンポが一定に保たれていても、感じられるエネルギーは上下するのです。
楽器の動き。 楽器の動きを要求すると、2つのプロパティを持つInstrumentActivityResultが返ります。1つは範囲のため、もう1つは動きのためのものです。1 Ranges APIは「各Instrumentを」楽器ごとの値に「対応付けるディクショナリを提供し」(その値の型が示される前にトランスクリプトが途切れています)、Appleは「楽器が存在するかどうかだけを知りたい」ときに範囲が適切な選択肢だと説明しています。1 activityプロパティはより詳細な情報を持ちます。それは「楽器をFloatのTimedValueに対応付け」、それらの値は「楽器が時間とともにどれだけ強く演奏しているかを表します」。1 Appleはこのactivityの結果を「オーディオリアクティブなアニメーションを駆動する優れた情報源」と呼んでいます。楽器ごとの瞬間ごとの強度こそ、ビジュアライザーがバインドしたいものだからです。1
ラウドネス。 フレームワークはラウドネスをLoudness Units Full Scale(LUFS)で測定します。これは「人間の耳が音量をどう知覚するかをモデル化するための業界標準」です。1 ラウドネス解析を要求すると、integrated、momentary、shortTermのラウドネスをサポートするLoudnessResult構造体が生成されます。1 integratedはオーディオ全体のラウドネスを表す単一の値です。momentaryとshortTermはどちらも100ミリ秒ごとにタイムスタンプ付きの値を提供しますが、異なるウィンドウを用います。momentaryは400ミリ秒のウィンドウを使って「ラウドネスの短く突発的なスパイク」を捉え、shortTermは3秒のウィンドウを使って「時間とともに変化するラウドネスの傾向をより滑らかに見せます」。1 結果はピーク値も持ちます。これはデシベルで測定された、オーディオの絶対的に最も高い音量です。1
ストリーミングラウドネスのAsyncSequence
上記のバッチAPIは、完成したファイルを解析します。ライブの作業のために、MusicUnderstandingSessionは「ラウドネスのストリーミングAPIも提供」しており、「値はフレームワークが解析したオーディオ100msごとにAsyncSequenceを通じて届けられます」。1 100msごとに新しいラウドネスの読み取り値が得られるというのは、リアルタイムのビジュアライザーが動作するペースそのものです。だからこそ、バッチAPIではなくこのAPIが、オーディオリアクティブなUIの中心となるのです。
使い方のパターンは、2つの並行タスクです。前と同じようにセッションを初期化し、それから「2つのタスクを設定します。1つは届いたラウドネスの結果を消費するタスク、もう1つは解析を開始するタスクです」。1 一方のタスクはシーケンスから値を待ち受けてアニメーションへと送り込み、もう一方が解析を前へと進めます。プロデューサーとコンシューマーは互いをブロックすることなく、並んで動作します。
ライブのオーディオを供給するには、AudioProviderを用意します。AudioProviderは「AsyncSequenceに準拠し、AVReadOnlyAudioPCMBufferオブジェクトを生成します」。1 Appleは終了の取り決めを明確に示しています。プロバイダーが「すべてのオーディオバッファを送信したら、完了を知らせるために最後にnilを送信しなければなりません」。1 末尾のnilを忘れると、消費側のタスクは決して終わらないオーディオを永遠に待ち続けます。プロバイダー自体がAsyncSequenceであることが、この設計の優美な点です。あなたのオーディオソースとフレームワークのラウドネス出力が、端から端まで同じ非同期反復の言語で語り合うのです。
さらに2つのセッション機能が、全体像を完成させます。Music Understandingのすべての結果はCodableに準拠しているため、完全な解析をエクスポートするのは「JSONEncoderを作成してセッション結果をエンコードするだけ」です。1 そしてサンプルアプリのVideoタイルは、結果が組み合わさる様子を示しています。それは「構造とペースを使って音楽に同期したビデオを作成し」、セクションの時間範囲を特定したうえで、各セクションのペース(1分あたりのイベント数を60秒で割った値)を使ってその範囲に何個のクリップが収まるかを決めます。エネルギッシュな部分には短く速いクリップを、穏やかな部分には長く遅いクリップを配置するのです。1
重要なポイント
オーディオ・メディアアプリの開発者へ:
analyze()ではなくanalyze(for:)から始めましょう。要求しなかった結果はどのみちnilで返ってくるので、描画する解析型だけを指定してフレームワークに残りを省かせます。1- UIでは
beatsPerMinuteを本当にオプショナルなものとして扱いましょう。nilはフレームワークがまだ2つのビートを見ていないことを意味するので、偽のテンポではなく保留中の状態を表示してください。1 - セッションを作成する前に、
AVURLAssetのPreferPreciseDurationAndTimingKeyをtrueに設定しましょう。Appleは正確な結果をこのフラグに結び付けているからです。1
リアルタイム・ビジュアライザーの作業へ:
- ライブのオーディオリアクティブなアニメーションは、ラウドネスの
AsyncSequence(100msごとの値)と、各楽器を時間ごとの強度のTimedValueに対応付ける楽器のactivityプロパティの上に構築しましょう。1 - コンシューマータスクと解析タスクを並行して実行し、カスタムの
AudioProviderが最後のAVReadOnlyAudioPCMBufferの後に最後のnilを送るようにして、ストリームがきれいに終了するようにしましょう。1
カタログ・ツーリングチームへ:
KeyResultとRhythmResultを使って音楽ライブラリをキーやテンポで並べ替えたりクラスタリングしたりし、CodableなSessionResultをJSONにエンコードして解析結果を保存し、再利用しましょう。1
FAQ
AppleのMusic Understandingフレームワークは何を解析しますか?
楽曲の6つの領域、すなわちキー、リズム、構造、ペース、楽器の動き、ラウドネスを解析します。それぞれが結果型(KeyResult、RhythmResult、StructureResult、PaceResult、InstrumentActivityResult、LoudnessResult)に対応し、SessionResultの中で返されます。フレームワークが信号処理とモデル推論を処理するため、DSPや機械学習の専門知識は必要ありません。1
Music Understandingはオンデバイスで動作しますか、それともクラウドで動作しますか?
オンデバイスです。Appleはフレームワークが「完全にオンデバイスで実行される」と述べており、解析するオーディオはプライバシーが守られ、オフラインでも動作します。この解析はネットワークに依存せず、Appleのプラットフォーム全体で機能します。1
必要な解析だけを取得するにはどうすればよいですか?
汎用のanalyze()ではなくanalyze(for:)を呼び出します。汎用の呼び出しはSessionResultのすべてのフィールドを埋めますが、対象を絞った呼び出しは要求した型だけを返し、残りをnilのままにします。Appleは不要な計算を避けるために「最高のパフォーマンス」を得る目的で型を指定することを推奨しています。1
TimedValueとRangedValueの違いは何ですか?
TimedValueは値を単一のCMTimeの瞬間に関連付け、RangedValueは値をCMTimeRangeの幅に関連付けます。どちらの型もフレームワーク全体に登場します。たとえばキーシグネチャは範囲付きの値として届き、楽器ごとの動きは時間付きの値として届きます。1
これを使ってライブのオーディオリアクティブなビジュアライザーを作るにはどうすればよいですか?
MusicUnderstandingSessionのストリーミングラウドネスAPIを使います。これは解析したオーディオ100msごとにAsyncSequenceで値を届けます。2つの並行タスク(1つは結果を消費し、もう1つは解析を駆動する)を実行し、AsyncSequenceに準拠してAVReadOnlyAudioPCMBufferオブジェクトを生成し、完了を知らせる最後のnilを送るカスタムのAudioProviderを通じてライブのオーディオを供給します。1
オンデバイスのオーディオ解析は、Appleが今年発表した他のメディアインテリジェンスと並んで位置づけられます。オンデバイスAIがiOS 27でSpotlightとメディアに到達する様子や、同じ問題のオーディオからテキストへの側面についてSpeechフレームワークとSFSpeechRecognizerの比較をご覧ください。Appleの組み込みモデルを完全に使い切ったときは、Core AIでApple silicon上に自前のモデルを動かすのが次のステップです。シリーズ全体のハブはApple Ecosystem Seriesです。
参考文献
-
Apple, WWDC 2026 session 253, Meet the Music Understanding framework. オンデバイス・プライバシー・オフラインの位置づけ、Final Cut Proのビート検出機能とiPadのモンタージュ機能、6つの解析領域(キー、リズム、構造、ペース、楽器の動き、ラウドネス)と楽曲の構成要素の定義、
AVAssetまたはオーディオプロバイダーから初期化されるMusicUnderstandingSession、analyze()とanalyze(for:)の対比およびオプショナルなフィールドからなるSessionResult、SwiftUIfileImporterを介したAVURLAssetとPreferPreciseDurationAndTimingKeyの設定、TimedValue/CMTimeとRangedValue/CMTimeRangeの型、KeyResult/KeySignature(トニックとモード)、RhythmResult/beatsPerMinute(2ビート未満ではオプショナル)、StructureResult(セクション、セグメント、フレーズ)、PaceResult、InstrumentActivityResult(rangesとactivity、activityはFloatのTimedValue)、LoudnessResult(LUFS、integrated/momentary/shortTermのウィンドウ、デシベルでのピーク)の各型、2つの並行タスクで100msごとに値を届けるストリーミングラウドネスのAsyncSequence、AsyncSequenceに準拠してAVReadOnlyAudioPCMBufferオブジェクトを生成し最後にnilを送るAudioProvider、Codableな結果とJSONEncoderによるエクスポート、そして構造とペースを用いたVideoタイルのアルゴリズムの出典。 ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩