View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

その他のビデオ

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • ShazamKitで、大規模なカスタムカタログを作成する

    ShazamKitを使用して、カスタムカタログを作成したり、あらゆるApp内のオーディオソースとの完全一致をサポートする方法を解説します。新しいShazamKit CLIを活用して、オーディオシグネチャを簡単に生成したり、大規模なカタログを構築したりする方法をご覧ください。また、連続もののテレビ番組やPodcastなど、大量のオーディオコンテンツをすばやくAppに同期する方法をはじめ、ShazamKit APIやSHMediaItemsの最新情報も紹介します。これにより、時間範囲を使用するオーディオソースの重要な瞬間に、Appが正確に応答できるようになります。 ShazamKitの詳細については、WWDC21の「ShazamKitの紹介」と「ShazamKitによるカスタムオーディオエクスペリエンスの構築」をご覧ください。

    リソース

    • ShazamKit
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC23

    • 優れたShazmKit体験の実現

    WWDC21

    • ShazamKitによるカスタムオーディオエクスペリエンスの構築
    • ShazamKitの詳細
  • このビデオを検索

    僕はNeil Foley ShazamKitチームのエンジニアです 2021年の ShazamKitの導入で Shazamの膨大な音楽カタログに オーディオをマッチングできる ようになりました また カスタムカタログ マッチングも導入されたことで デベロッパは自分のオーディオを マッチングさせて 同期体験が 提供できるようになりました さらに大規模に カスタムカタログとの連携を 合理化した重要な アップデートが行われました 今回は ShazamKitの既存の コンセプトを使っていきます 例えば 署名やカタログ メディアアイテムなどです これらに馴染みのない方は 画面の下に出ている WWDC21に行われた 2つのトークの内容を ご覧ください 簡単に言うとShazamKitは オーディオをマッチングできる 特別なフォーマットに 変換してくれます これをシグネチャと 呼んでいます メタデータを含むメディアアイテムと 組み合わせてできるのが 参照シグネチャで カスタムカタログと言う ファイルにまとめて 保管することができます 簡単な概要は以上で 今度は大規模な カスタムカタログの構築と 素晴らしいカタログにするための コツについてお話します 現在の カスタムカタログ ワークフローなら マッチングしたいコンテンツが 少ない場合は カスタムカタログでの作業は いたってシンプルです その手順は次の通りです ShazamKitが使用できる形式で オーディオを録音します

    シグネチャジェネレータを使って それをシグネチャにします

    それにメタデータを付加して カスタムカタログに保存します それだけで Shazam体験を 提供できるのです ですが オーディオプログラミングに 詳しくない場合は 大変に思えるかも知れませんね サンプルレートやバッファも 経験豊富なデベロッパでも 手こずることがあります 膨大な量のコンテンツを 取り扱う場合 例えばテレビ番組の10シーズン分なら どうなるでしょう?

    このワークフローは かなり困難になり得ます

    コンテンツの量が膨大だと 管理不能になりやすいものです このワークフローを 自分で改善するには オーディオをシグネチャに変える コードを書いて メディアアイテムを取り込んで関連付ける ために更にコードを書き コンテンツを変える度に これを繰り返すことになります オーディオのマッチングに これは膨大過ぎる作業です そしてコンテンツを ShazamKitと同期したければ 複雑な論理を使って何をいつ どうするか計算することになります このワークフローを合理化するために ShazamKitが大幅に機能強化されました まずは 簡単なデモをお見せします これは2021年にAlexが お見せした FoodMathAppで オンスクリーンレッスンと 算数クイズを同期しています 最新の ShazamKit機能で アップデートしてあり その同期状況を見るために FoodMathビデオを再生します

    26秒までスキップ 2個… 3個の青りんごがあります 全部でりんごはいくつありますか? それでは皆さん… 始め! ではそこまで! 答えは何でしょうか 56秒までスキップ 今日は少しひねりますよ お店に行った時 最初は2個の赤いりんごで… それから2個の青りんごを 買いました 今度は全部でいくつの りんごをもっていたでしょうか? それでは皆さん… 始め!

    ではそこまで! 問題なさそうです リッチなコンテンツが動画と同期し 僕が“始め!”と言った時 ピッタリのタイミングで メニューが表示されました またコンテンツの関連性がなくなると キューに合わせて消えていました 一体どうやったのでしょう? コードを見てみましょう シンプルなループだけです 以前使っていた デリゲートのコールバックの代わりに 非同期のシーケンスを使っています マッチしたか していないか エラーかを 表す列挙型を戻してくれます 必要なのはマッチしたものだけなので ループをそれに限定します 結果の表示を作成するために メディアアイテムを 必要なコンテンツだけに減らします

    Appの中身はこれぐらいで 作成した matchResultの生み出す SwiftUIビューだけです 複雑な論理もタイミングコードもなく 完璧に同期してくれます なぜそんなに上手く同期できるのか やはり疑問ですね FoodMathsの秘密は リッチな カスタムカタログにあります ShazamKitの補完として作成した 簡易ツールでカタログを作りましたが 皆さんも同様にApp内に リッチな体験を生み出せます Shazam CLIは macOS 13の 一部として登場し コンテンツの同期を簡易化する 方法を提供します カスタムカタログの作成に関連する 反復的タスクを自動化する サポートをしてくれます 先ほどお見せした カスタムカタログを アップデートしましょう 別のデモをお見せします

    このフォルダにあるのは FoodMathのビデオファイルと ターミナルも入っています CLIを使って動画を シグネチャに変換します シグネチャコマンド使用します

    ビデオファイルを入力としてパスし シグネチャ出力を特定します

    シグネチャができました

    これをメディアアイテムと 一緒に合わせて カスタムカタログを作ります CLIはメディアアイテムの記述に コンマで分けられた シンプルなファイルを受け付けるので ここにコピーします

    コンテンツの同期に必要なものが 全て記述されています

    特定したタイトルはここに… そして方程式のために定義した カスタム JSONフィールドがここです ヘッダーはメディアアイテム プロパティに関連しています マッピングの詳細については カスタムカタログ作成コマンドを ヘルプのフラグ付きで 実行してください

    CSVヘッダーとメディアアイテムプロパティの 関係性が記述されています では両者を合わせて カスタムカタログを作りましょう 作成コマンドを実行して…

    シグネチャファイルを csvファイルに パスするとカタログを出力します

    これでカタログができました 僕は最新の FoodMathエピソードに 既にアクセスできるので カタログファイルに追加します ファイルをコピーします

    新エピソードのメディアアイテムが ここにあります

    アップデートコマンド実行して 新しいメディア ビデオそしてカタログを 渡してアップデートします

    カタログのアップデート完了です カタログの作成方法を 簡単に見てきましたが 僕のようなタイプの人は これをスクリプトしたいですね

    FoodMathAppはかなり 新しいエピソードがあって その全てをこのカタログに 追加したいと思います 全部のエピソードフォルダをループし それを合わせてカスタムカタログに 入れる単純なスクリプトを書きました では実行します

    できました これで1つのカタログに 全ての FoodMathエピソードと カタログ内の詳細を示すのに スクリプトの表示コマンドが使用されました 全部入っているようです FoodMathプロジェクトは既に 新しいカタログを参照しています では 作成および実行して 算数を楽しみましょうか

    30秒までスキップ 全部でりんごはいくつありますか? それでは皆さん… 始め! では そこまで 答えを見てみましょう あの人 イイですね 素晴らしいエピソードだ 新しいエピソードはどうでしょう 見てみましょう

    15秒までスキップ - 何年もかけて美味しいワカモレの 秘密を探ってきた僕が お気に入りのワカモレのレシピを 書いてみました 4個のアボカドが必要です 友人が遊びに来るのですが 2人だけなら半分の量の ワカモレで充分です アボカドは何個必要でしょうか? それでは皆さん… 始め!

    その通り アボカド2個です 一緒にワカモレを作りましょう

    味見してみましょう

    うーん とても美味しい 楽しんでいただけたでしょうか それでは また次回

    そうか 新しいホストとは なるほど とにかくあっという間に リッチな同期体験が作成できました Shazam CLIはコマンドの リッチなセットをサポートします 見ていきましょう

    オーディオトラックを含む あらゆるメディアファイルから シグネチャが作成できます シグネチャとメディアアイテムを 合わせてカスタムカタログが 作成できます カタログのコンテンツを 表示できます シグネチャとメディアアイテム 両方の 追加・削除・エクスポートが可能です 次は CLIが FoodMathビデオから シグネチャ作成した方法です

    SHSignatureGeneratorには新メソッドの signatureFromAssetがあり 全プラットフォームで利用可能です このメソッドではメディアから手動で オーディオバッファを引き抜く必要はありません オーディオトラックのついた AVAssetをパスし シグネチャに変えるだけです アセットに複数のトラックがある場合は 全てがミックスされ 必ず シグネチャ内に 全てがキャプチャされます では メディアを表すシグネチャが あったとしても どうやって正確にコンテンツを 同期したのでしょうか? Timed MediaItem APIを使いました メディアアイテムに時間を 付与することで 開始時間および終了時間の特定が 簡単になりました メディアアイテムは複数の 時間範囲を持つ場合があり シグネチャの一部分以外も ターゲットにしています コーラスをターゲットにした メディアアイテムを考えてみましょう 歌われている部分を表す 時間範囲が追加できます

    時間範囲の特定が役に立つのは 開始時間と終了時間が 通知された場合だけです ShazamKitは時間の範囲と同期した マッチコールバックを送り 開始時に1つと終了時に1つです シグネチャは多くのメディアアイテムを 包括できるので このコールバックは 特定の時間の範囲内にある メディアアイテムのみを含みます どのメディアアイテムがどの順番で コールバックに戻されるのか 少しだけルールがありますので それを見てみましょう

    時間範囲の外にあるものは 戻されません 時間範囲の中にあれば 戻されますが 最近のイベントが 最初に戻されます

    時間範囲のないものは 常に最後に戻されますが 順序はバラバラです 時間範囲のないものは レファレンス全体に適用される 全体的な情報を保存するのに 適した場所だと言えます FoodMathの例では エピソード名の保存場所にしました 他のメディアアイテムが 見えない場合に現れます

    付け加えると メディアアイテムの 全てに時間範囲があって どれもスコープ外であれば ShazamKitが常に基本的マッチ情報を付けて メディアアイテムを戻します これによって常に 重要なプロパティが手に入ります 例えば predictedCurrentMatchオフセットや frequencySkewなどです コードでも簡単です timeRangesのメディアアイテム プロパティを特定することで 時間付きのメディアアイテムが 作成されます Swift範囲の配列です timeRangesプロパティを使って リードバックすることも可能です Objective-Cのプログラマーには 新しい SHRangeのクラスが 完全互換品として使えます 作成方法は分かったので… 素晴らしいカスタムカタログを作る コツをいくつか見てみましょう メディア1つに対して数多くの 小さな シグネチャを作らないように シグネチャはそれが表すメディアへの 1対1のマッピングなので 歌であろうとビデオであろうと 1つのオーディオに対し 最初から最後までで 1つの シグネチャを作りましょう

    シグネチャが長ければ ShazamKitは 音のピークをマッチする機会が増え その結果 正確性が向上するわけです また 複数の参照シグネチャが 重複する クエリ シグネチャのような 問題も避けられます

    新しいTimed MediaItem APIを を使えば 個々のエリアで同期コンテンツを ターゲットにできます 1つのオーディオを複数のシグネチャに 分割する必要はありません お見せした例では メディアは1つでしたが メディアアイテムは複数ありました ですが膨大な量のコンテンツに Shazamを利用したい場合 どうすればいいのでしょうか? どう分ければいいのでしょうか? カスタムカタログのコンテンツを 分割する場合は ある種の犠牲が必要です 各メディアアセットに 個々のカタログを作るなら オーディオのどの部分が 演奏されているか知っていないと 正しいカタログを取り込めません そしてそれらを全部 1つのカタログに入れたら ダウンロードは大きくなり メモリ使用量も増えますが もっと多くのオーディオピースを マッチできるわけです 作成したカタログファイルは しっかり絞りましょう 例えば 1曲ごとや全アルバムに カタログを1つ作っても アーティストの全ディスコグラフィーに カタログ1つはやめましょう 分別というのは 実行時に何を 取り込みたいかを決める事です custom catalog add APIで それができます

    自分のユースケースに合うか 試してみてください 同じ様に聞こえるオーディオ アセットが複数ある場合 例えば同じイントロで始まる テレビ番組など 各エピソードに カスタム体験を提供したり 別のトラックで標本化された 曲を提供したければ 周波数スキューを差別化要因に 使うのもいいでしょう オーディオのスキューは録音の周波数を 上げたり下げたりすることです これはオーディオの 聞こえ方に影響を与えますが わずかなスキューなら ShazamKitには分かっても 平均的な人間の耳では無理です ですから録音をして カスタムカタログを作ったら 僅かに周波数を変えて 再生すれば ShazamKitは マッチングを行い frequencySkewプロパティを通して スキュー量を報告します コードでのやり方はこちらです

    人間の耳では 聞き分けられないけれど ShazamKitには聞き分けられる 程度のスキュー量は きちんと決まっています

    5%未満のスキューなら安全で 複数のスキュー済みの録音も 区別がつきます 有効に活用したいなら frequencySkewRangesを使いましょう 特定のスキュー範囲にある メディアアイテムのみ 戻されてきます

    その範囲はパーセントで表され オリジナルからどれだけ 変わっているかを意味します ゼロの値はスキューされて いないことを意味し .01の値は1%のスキューを意味します frequencySkewRangeプロパティを使えば メディアアイテムのプロパティにアクセスできます

    Appでのやり方を 段階を踏んでお見せしましょう まずオリジナルのオーディオ録音から 参照シグネチャを作成します MediaItemを3から4%の 周波数スキューで制限します カスタムカタログ内に入れます

    3から4%スキューされた オーディオを再生すると メディアアイテムが 戻されます スキュー無しやスキューの範囲を 外れたものを再生しても 戻されることはありません 以上が周波数スキューです

    ShazamKitの今年のアップデートを ご覧になった今 素晴らしい同期体験を 生み出す準備ができましたね そのために重要な事をまとめます まずは メディアアセットごとに 1つの シグネチャを作成しましょう ShazamKitなら精度も上がり 作成パイプラインもシンプルです シグネチャの作成には SHSignatureGeneratorsの signatureFromAssetを使いましょう 非常に幅広いメディアを 受け入れるので 低レベルのオーディオの詳細に 時間を費やす必要はありません

    新しいTimed MediaItem APIを使って 対象を絞って 同期コンテンツを ターゲットしましょう そしてカスタムカタログの作成は Shazam CLIに合理化させましょう 膨大な量のメディアと 格闘する必要を無くすので 皆さんは素晴らしい体験の 作成に集中できます ShazamKitの最新アップデートを お楽しみいただけたでしょうか 全てに役立てていただければ 非常に光栄です お話した全ての情報や ドキュメントへのリンクは 本セッションに添付されています ご清聴ありがとうございました

    • 4:26 - Food Math Matcher

      /*
      See LICENSE folder for this sample’s licensing information.
      
      Abstract:
      The model that is responsible for matching against the catalog and update the SwiftUI Views.
      */
      
      import ShazamKit
      import AVFAudio
      
      struct MatchResult {
          var title: String?
          var equation: Equation?
          var episode: Episode?
          var answerRange: ClosedRange<Int>?
          
          var hasContent: Bool {
              equation != nil || title != nil || answerRange != nil
          }
      }
      
      class Matcher: NSObject, ObservableObject, SHSessionDelegate {
          @Published var matchResult: MatchResult?
          
          private var session: SHSession!
          private let audioEngine = AVAudioEngine()
          private var matchingTask: Task<Void, Never>? = nil
          
          func match(catalog: SHCustomCatalog) throws {
              
              session = SHSession(catalog: catalog)
              session.delegate = self
              
              let audioFormat = AVAudioFormat(standardFormatWithSampleRate: audioEngine.inputNode.outputFormat(forBus: 0).sampleRate,
                                              channels: 1)
              audioEngine.inputNode.installTap(onBus: 0, bufferSize: 2048, format: audioFormat) { [weak session] buffer, audioTime in
                  session?.matchStreamingBuffer(buffer, at: audioTime)
              }
              
              try AVAudioSession.sharedInstance().setCategory(.record)
              AVAudioSession.sharedInstance().requestRecordPermission { [weak self] success in
                  guard success, let self = self else { return }
                  
                  Task.detached {
                      try? self.audioEngine.start()
                  }
              }
              
              Task { @MainActor in
                  for await case .match(let match) in session.results {
                      self.matchResult = match.matchResult
                  }
              }
          }
      }
      
      extension SHMatch {
      
          var matchResult: MatchResult {
              mediaItems.reduce(into: MatchResult()) { result, mediaItem in
                  result.title = result.title ?? mediaItem.title
                  result.episode = result.episode ?? mediaItem.episode
                  result.equation = result.equation ?? mediaItem.equation
                  result.answerRange = result.answerRange ?? mediaItem.answerRange
              }
          }
      }
    • 13:51 - Timed Media Items

      // Restrict this media item to only describe the first 5 seconds
      
       let mediaItem = SHMediaItem(properties: [
                  .title: "Title",
                  .timeRanges:[0.0..<5.0]
              ])
      
       let timeRanges: [Range<TimeInterval>] = mediaItem.timeRanges
    • 16:02 - Combine Catalogs

      let parentCatalog = SHCustomCatalog()
      
      parentCatalog.add(from: URL(fileURLWithPath: "/path/to/Episode1.shazamcatalog"))
      parentCatalog.add(from: URL(fileURLWithPath: "/path/to/Episode2.shazamcatalog"))
      parentCatalog.add(from: URL(fileURLWithPath: "/path/to/Episode3.shazamcatalog"))
    • 16:58 - Frequency Skew

      func within(range: Range<Float>, for matchedMediaItem: SHMatchedMediaItem) -> Bool {
              
      	range.contains(matchedMediaItem.frequencySkew)
      }
    • 17:21 - Frequency Skew Ranges

      // Restrict this media item to only describe the first 5 seconds
      
       let mediaItem = SHMediaItem(properties: [
                  .title: “Frequency Skewed Audio”,
                  .frequencySkewRanges:[0.01..<0.02]
              ])
      
       let frequencySkewRanges: [Range<Float>] = mediaItem.frequencySkewRanges

Developer Footer

  • ビデオ
  • WWDC22
  • ShazamKitで、大規模なカスタムカタログを作成する
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン