适用于 iOS 的 ShazamKit 入门教程

4,845 阅读19分钟

在本教程中,您将:

  • 了解 Shazam 的识别机制。
  • 创建 DevCompanion ,一个简单的 Shazam片段,与流行的、已发布的音乐和歌曲相匹配。
  • 匹配视频中的自定义音频。
  • 可见视频播放位置更改应用内容。

如果你不是,请不要担心。只需要在笔记本电脑上播放首首歌曲,就问 Siri:“这首歌是什么本?”或下载Shazam 应用程序。

入门

01.png

DevCompanion 有两个视图:

  • 在什么?:用户可以在其中匹配流行音乐,就像 Shazam 一样。
  • 视频内容:用户可以在 raywenderlich.com 上观看 SwiftUI 视频课程时查看注释和其他内容。

打开MatchingHelper.swift并查看代码。这是一个空的帮助程序类,您将在其中编写 ShazamKit 识别代码。

现在不要担心其他文件。创建自定义音频体验时,您将在本教程后面看到您。现在,您将了解更多关于 Shazam 如何识别和匹配音频的信息。

注意:对于本教程,您的 Xcode 13 和运行 iOS 13 和运行 iOS 1。

您还需要一个 Apple 开发帐户人员使用 ShazamKit 应用程序服务配置应用程序 ID。

了解Shazam的匹配机制

在编写代码和使用 ShazamKit API 之前,必须了解 Shazam 如何在幕后工作。

使用 Shaza 时,可以在播放时点击显示大识别*Shazam。*立即找到该应用程序会听几首歌曲,然后在您的匹配项中播放歌曲信息。您可以匹配的任何部分。

这就是引擎盖下的内容:

  1. 该应用程序使用实例具有预定义程序的开始形式的流。
  2. Shazam 库(现在称为 ShazamKit 从应用程序展示的签名签名*)*。
  3. 然后,ShazamKit 会将这个音频签名的查询请求发送到 Shazam API。Shazam 服务将签名与 Shazam 目录中流行音乐的签名进行匹配。
  4. 如果,API 给排序的 ShazamKit 的元数据匹配返回。
  5. ShazamKit 调用传递元数据的正确委托。
  6. 结果,由应用程序逻辑来显示轨迹信息。

,您将了解有关 Shazam 签名和目录的更多信息。

Shazam签名

Shazam通过生成高随后的部分的创建签名,或者是雷声和识别的部分。

签名对原始音频不观看,以确保原始音频的隐私。

在此过程中,Shazam 将应用程序发送的查询签名与参考签名进行匹配。参考签名是从整首歌曲或曲目生成的。

例如,可以识别出大部分的Shazam应用程序在不同的背景下都能获得匹配。 和索引,他们因为更多的占用空间比原始音频小。

您可以在 Shazam 创始人 Avery Wang 的个人研究论文中了解更多关于 Shazam 算法的信息。

,您将探索 Shazam 目录。

Shazam目录

如前所述,Shazam 将签名参考签名进行匹配。

02.png

Shazam 目录包含几乎所有流行歌曲的参考签名和元数据。您还可以在应用程序中本地创建自定义目录,为您存储音轨并参考签名和数据。您将在本教程后面创建定义目录。

理论到此为止。接下来,您将学习如何让应用识别流行音乐。

将音乐与 Shazam 的目录相匹配

MatchingHelper.swift代码:

导入AVFAudio
进口基金会导入
ShazamKitMatchingHelper : NSObject {变量
  会话:SHSessionAu
  私有 audioEngine =  AV

  私有 var matchHandler: (( SHMatchedMediaItem ?, Error ?) -> Void ) ?

  init ( matchHandler  handler : (( SHMatchedMediaItem ?, Error ?) -> Void ) ? ) {
    matchHandler =处理程序
  }
}

它是一个控制麦克风并使用 ShazamKit 识别音频的辅助类。在顶部,您可以看到导入 ShazamKit 的代码以及AVFAudio. 您需要 AVFAudio 才能使用麦克风和捕获音频。

MatchingHelper也是子类NSObject,因为任何符合SHSessionDelegate.

看一下MatchingHelper的属性:

  • session:您将用于与 Shazam 服务通信的 ShazamKit 会话。
  • audioEngineAVAudioEngine您将用于从麦克风捕获音频的实例。
  • matchHandler:应用程序视图将实现的处理程序块。它在识别过程完成时调用。

初始化程序确保matchHandler在您创建类的实例时设置。

在初始化器下面添加以下方法:

func  match ( catalog : SHCustomCatalog ? =  nil ) throws {
   // 1. 实例化 SHSession 
  if  let catalog = catalog {
    session =  SHSession(目录:目录)
  }其他{
    会话=  SHSession ()
  }

  // 2. 设置 SHSession 委托
  会话? .delegate = 自我

  // 3. 准备捕获音频
  let audioFormat =  AVAudioFormat (
    standardFormatWithSampleRate:
      audioEngine.inputNode.outputFormat(forBus: 0 ).sampleRate,
    渠道:1)
  audioEngine.inputNode.installTap(
    总线上: 0 ,
    缓冲区大小:2048,
    格式:音频格式
  ) { [ weak session] buffer, audioTime in  
    // 回调捕获的音频缓冲区
    会话?.matchStreamingBuffer(缓冲区,在:audioTime)
  }

  // 4. 使用 AVAudioEngine 开始捕获音频
  try  AVAudioSession .sharedInstance().setCategory(.record)
   AVAudioSession .sharedInstance()
    .requestRecordPermission { [弱 自我]守卫成功
      
        成功,
        让 self  =  self 
      else { return }
      试试? 自.audioEngine.start()
    }
}

match(catalog:)是应用程序代码的其余部分将用于使用 ShazamKit 识别音频的方法。SHCustomCatalog如果要与自定义目录匹配,它需要一个可选的类型参数。

看看每一步:

  1. 首先,SHSession如果您使用自定义目录,则创建一个目录并将其传递给它。

    SHSession如果您不提供目录,则默认为 Shazam 目录,该目录适用于应用程序的第一部分。

  2. 您设置SHSession委托,稍后您将实现它。

  3. 您调用AVAudioEngine's AVAudioNode.installTap(onBus:bufferSize:format:block:),这是一种准备音频输入节点的方法。在传递捕获的音频缓冲区的回调中,您调用SHSession.matchStreamingBuffer(_:at:). 这会将缓冲区中的音频转换为 Shazam 签名,并与所选目录中的参考签名进行匹配。

  4. 您将AVAudioSession类别或模式设置为录制。AVAudioSession然后,您在应用程序第一次运行时通过调用'srequestRecordPermission(_:)向用户询问 麦克风权限来请求麦克风录音权限。

    最后,您通过调用 开始录制AVAudioEngine.start()

注意NSMicrophoneUsageDescription已经在项目的Info.plist 中设置。

matchStreamingBuffer(_:at:)处理捕获音频并将其传递给 ShazamKit。或者,您可以使用SHSignatureGenerator生成签名对象并将其传递给matchof SHSession。但是,matchStreamingBuffer(_:at:)它适用于连续音频,因此适合您的用例。

接下来,您将实现 Shazam Session 委托。

探索 ShazamKit 会话

在连接 UI 之前还有两个步骤。首先,您需要实施SHSessionDelegate以处理匹配的成功和失败。

在MatchingHelper.swift的末尾添加以下类扩展:

扩展 MatchingHelper : SHSessionDelegate {
   func  session ( _  session : SHSession , didFind  match : SHMatch ) {
     DispatchQueue .main.async { [ weak  self ] in 
      guard  let  self  =  self  else {
         return
      }

      if  let handler =  self .matchHandler {
        handler(match.mediaItems.first, nil )
         // 停止捕获音频
      }
    }
  }
}  

在此扩展中,您实现SHSessionDelegate. 当录制的签名与目录中的歌曲匹配时 SHSession调用。session(_:didFind:)它有两个参数:SHSession调用它的来源和一个SHMatch包含结果的对象。

在这里,您检查是否matchHandler已设置,并通过以下参数调用它:

  • SHMatchedMediaItem返回mediaItems的第一个SHMatch:如果查询签名匹配目录中的多首歌曲,ShazamKit 可能会返回多个匹配项。匹配按匹配质量排序,第一个具有最高质量。
  • 错误类型:由于这是成功的,因此您传递nil

在下一节中,您将在 SwiftUI 中实现此处理程序块。

紧随其后session(_:didFind:),添加:

func  session (
   _session  : SHSession , 
   didNotFindMatchFor签名: SHSignature , 
   error :错误?_ 
) {
  DispatchQueue .main.async { [ weak  self ] in 
    guard  let  self  =  self  else {
       return
    }

    if  let handler =  self .matchHandler {
      handler( nil , error)
       // 停止捕获音频
    }                          
  }
}

session(_:didNotFindMatchFor:error:)``SHSession是当目录中没有与查询签名匹配的歌曲或发生阻止匹配的错误时调用的委托方法。它返回第三个参数中发生的错误,或者nil如果查询签名在 Shazam 目录中没有匹配项。与您在 中所做的类似session(_:didFind:),您调用相同的处理程序块并传入错误。

最后,为了遵守 Apple 的麦克风使用指南并保护用户隐私,您需要在调用两个委托方法中的任何一个时停止捕获音频。

match(catalog:)在 的主体之后添加以下方法MatchingHelper

函数 停止监听(){
  音频引擎.stop()
  audioEngine.inputNode.removeTap(onBus: 0 )
}

然后,调用stopListening()上面的两个委托方法。替换以下注释:

// 停止捕获音频

和:

自我.stopListening() 

接下来,您将显示匹配结果。

显示匹配的乐曲

Shazam 克隆的最后一部分是 UI。打开SongMatchView.swift并检查画布中的预览:

03.png

视图由两部分组成。带有圆形绿色方块的顶部是您将显示歌曲信息的地方。底部有启动匹配过程的匹配按钮。

首先,你需要一个MatchHelper对象。在 顶部SongMatchView,添加:

@State  var matcher:MatchingHelper?

然后,在视图的末尾struct,紧随其后body,添加:

func  songMatched(项目:SHMatchedMediaItem?,错误:错误?){
  isListening =  false
  如果错误!=  nil {
    status =  "无法匹配音频:(" 
    print ( String (描述: error.debugDescription))
  }其他{
    status =  "歌曲匹配!" 
    print ( "找到歌曲!" )
    标题=项目?。标题
    副标题=项目?。字幕
    艺术家=物品?。艺术家
    coverUrl =项目?.artworkURL
  }
}

songMatched(item:error:)``MatchingHelper是完成匹配时调用的方法。它:

  • 设置isListeningfalse。因此,UI 会更新以向用户显示应用程序不再记录并隐藏活动指示器。
  • 检查error参数。如果它不是 nil,则存在错误,因此它会更新用户看到的状态并将错误记录到控制台。
  • 如果没有错误,它会告诉用户它找到了匹配项并使用歌曲元数据更新其他属性。

SHMatchedMediaItem是 的子类SHMediaItem。它为匹配的项目继承媒体项目的元数据属性,例如歌曲的标题艺术家流派艺术品 URL视频 URL。 它还具有特定于匹配项的其他属性,例如frequencySkew匹配音频和查询音频之间的频率差异。

接下来,在 末尾NavigationView,添加:

.onAppear {
  如果匹配器==  nil {
    matcher =  MatchingHelper (matchHandler: songMatched)
  }
}
.onDisappear {
  isListening = 假
  匹配器?.stopListening()
  状态=  ""
}

在这里,您实例化MatchHelper视图出现时刚刚添加的传递处理程序。当视图消失时,例如,当您切换到另一个选项卡时,您可以通过调用来停止识别过程stopListening()

最后找到Match按钮代码,如下:

按钮(“匹配”){
}
.font(.title)

在按钮操作块中,添加:

status =  "Listening..." 
isListening =  true 
do {
   try matcher ? 。匹配()
}抓{
  status =  "匹配歌曲时出错"
}

这就是魔术开始的地方。您更改status以告诉用户应用程序正在侦听并调用match()以启动匹配过程。当SHSession返回结果时MatchingHelper,它调用songMatched(item:error:).

接下来,您将测试该应用程序。

测试应用程序

注意:在撰写本文时,您只能在物理设备上测试 ShazamKit。您还需要一个 Apple 开发人员帐户才能在 ShazamKit 应用服务中注册一个应用 ID。您必须在 Apple Developer Portal 上手动执行此配置:

4.1.png

之后,相应地设置捆绑标识符和签名设置。

要尝试匹配歌曲,请在 iPhone 上构建并运行该应用程序。

04.png

打开以下YouTube 链接播放歌曲。你能猜出这首歌吗?

轻点“匹配”并将您的 iPhone 靠近扬声器。几秒钟后,你会看到匹配:

05.png

万岁!该应用程序成功匹配了歌曲。

使用自定义目录

您学习了如何使用 ShazamKit 将音频与 Shazam 目录进行匹配。如果您想匹配您的音乐作品或视频内容怎么办?ShazamKit 为您提供保障。

现在您将实现 DevCompanion 的剩余部分,即视频内容选项卡。您将首先将音频与您将创建的自定义目录进行匹配。

该应用程序将识别*您的第一个 iOS 和 SwiftUI 应用程序的介绍视频:从零开始的应用程序视频课程。这是一个很棒的免费视频课程,用于学习 SwiftUI 的基础知识。*

在此之前,您需要了解有关 Shazam 签名文件的更多信息。

Shazam 签名文件

如您之前所见,Shazam 目录是签名及其元数据的集合。但是 Shazam 签名是什么样的?

Shazam 签名存储在扩展名为*.shazamsignature*的文件中。它们是不透明的文件,您可以安全地从远程服务器共享或下载它们。

在项目导航器中,展开Signatures。您会找到DevCompanion.shazamsignature,这是 SwiftUI 课程介绍视频的 Shazam 签名文件。

此签名文件将是您的自定义目录中的参考签名。ShazamKit 会将查询签名与此签名文件进行比较,以确定您是在播放介绍视频还是其他内容。

接下来,您将创建一个自定义目录。

创建自定义目录

在Data中创建一个 Swift 文件。在 Project navigator 中,右键单击Data文件夹并选择New File ...。

06.png

然后,选择Swift File并单击Next

07.png

接下来,将其命名为DevVideosCatalog.swift并单击Create。最后,打开文件并添加:

导入ShazamKit

枚举 DevVideosCatalog {
   static  func  catalog () throws -> SHCustomCatalog ? {
     // 1. 确保签名文件存在
    guard  let signaturePath =  Bundle .main.url(
      forResource: "DevCompanion" ,
      withExtension: "shazamsignature" ) else {
       return  nil
    }

    // 2. 读取签名文件并实例化一个 SHSignature 
    let signatureData =  try  Data (contentsOf: signaturePath)
     let refSignature =  try  SHSignature (dataRepresentation: signatureData)

    // 3. 用这个签名的元数据创建一个 SHMediaItem 
    let videoMetadata =  SHMediaItem (
      特性: [
        .title: "你的第一个 iOS 和 SwiftUI 应用:一个从零开始的应用" ,
        .subtitle: "简介" ,
        .艺术家:“雷·温德利希”
      ])
    
    // 4. 创建自定义目录。
    让customCatalog =  SHCustomCatalog ()
    试试customCatalog.addReferenceSignature(
      参考签名,
      表示:[videoMetadata])

    返回自定义目录
  }
}

catalog()返回 type 的对象,SHCustomCatalogShazamKit 为自定义目录提供的类型。这是一个静态方法,用于初始化您的自定义目录并返回它。在这里,它:

  1. 检查应用程序包中的 Shazam 签名文件DevCompanion.shazamsignature。如果文件不存在,则返回 nil。
  2. 读取Data签名文件的内容并初始化refSignature,这是一个SHSignatureShazamKit 用于存储签名数据的容器类型。
  3. 定义videoMetadata,SwiftUI 课程介绍视频的元数据。这是SHMediaItem具有一些预定义属性的。
  4. 初始化目录,然后调用SHCustomCatalog.addReferenceSignature(_:representing:)以使用您的元数据设置目录的引用签名。

接下来,您将根据这个新的自定义目录匹配音频。

将音频与自定义目录匹配

打开VideoMatchView.swift并查看 Canvas 中的预览。

08.png

该视图看起来类似于SongMatchView

VideoMatchView删除和的整个当前代码VideoMatchView_Previews。然后,取消注释文件末尾的代码以替换它们。

这个实现VideoMatchView现在与 相同SongMatchView,除了标签名称不同,因为您匹配的是开发视频而不是歌曲。

例如,看看VideoMatchView.videoMatched(result:error:)

func  videoMatched(结果:SHMatchedMediaItem?,错误:错误?){
  isListening =  false
  如果错误!=  nil {
    status =  "无法匹配音频:(" 
    print ( String (描述: error.debugDescription))
  }其他{
    课程=结果?.title ?? 课程
    情节=结果?.副标题??插曲
    作者=结果?.艺术家??作者
  }
}

在这里,您将course文本设置为SHMatchedMediaItem's title,将episode文本设置为subtitle,将author文本设置为artist。毕竟,开发者和内容创作者不是艺术家吗?

接下来,找到Start Episode按钮并查看其操作代码:

做{
  尝试匹配器?。匹配()
  }抓{
    status =  "匹配歌曲时出错"
}

正如您在前面的匹配音乐与 Shazam 的目录部分中看到的那样,MatchingHelper.match(catalog:)采用类型的可选参数将SHCustomCatalog其传递给SHSession. 如果未传递自定义目录,则SHSession默认为 Shazam 目录。你需要改变它。

替换这一行:

尝试匹配器?。匹配()

和:

尝试匹配器?.match(目录:DevVideosCatalog .catalog())

在这里,您将自定义目录传递给MatchingHelperSHSession在下一场比赛中使用它。现在,您已准备好进行测试。

打开 SwiftUI 课程介绍并播放视频。构建并运行。切换到视频内容选项卡并将手机靠近扬声器,以便它可以听到视频的配乐。

09.png

现在,点击开始剧集。几秒钟后,您将在顶部看到视频信息:

10.png

该应用程序匹配您自定义目录中的音频!

您还可以将自定义目录保存为不透明文件,就像使用SHCustomCatalog.write(to:). 此文件具有扩展名*.shazamcatalog*。要了解更多信息,请查看Apple 文档

注意:根据自定义目录匹配音频与匹配 Shazam 目录没有什么不同,只是ShazamKit在您的设备上进行本地匹配并且不必与 Shazam 的服务器通信。

注意:您也可以使用以下步骤创建自己的*.shazamsignature*文件:

  1. 开始捕获音频AVAudioEngine- 与您之前所做的相同。
  2. AVAudioNode.installTap(onBus:bufferSize:format:block:), callSHSignatureGenerator的回调中,从回调参数中append(_:at:)传递bufferand 。audioTime这将从捕获的音频中生成一个签名。
  3. 曲目结束时停止录制。
  4. 写入SHSignatureGenerator.signature().dataRepresentation文件。

查看教程材料文件夹中的ShazamSignatureGenerator项目。这是一个示例应用程序,可让您创建 Shazam 签名并将其导出到*.shazamsignature*文件。

接下来,您将创建自定义音频体验。

将应用程序内容与音频同步

您将添加到 DevCompanion 的最后一个功能会在用户观看 SwiftUI 课程介绍时向他们展示其他内容。您将向他们展示说明 Ray 在介绍课程时所谈论的部分的注释。看看下面的插图:

11.png

该应用程序会将内容与视频播放位置同步。例如:

  • 00:05时,VideoMatchView将显示*Welcome!*和插图。
  • 00:14,当 Ray 描述您将在课程中构建的应用程序时,视图显示您的第一个 SwiftUI 应用程序!和应用程序的屏幕截图。
  • 00:47 Ray 谈到课程结构的第一部分时,视图显示Course Overview: SwiftUI vs UIKit,该部分的标题和插图。

这不是很酷吗?接下来,您将实现这些注释。

实现注解

您将创建一个简单struct的标题、要显示的图像和显示它们的时间。

在 Project navigator 中,展开Data并单击VideoAnnotation.swift将其打开。在文件的开头,在注释的扩展名之前添加以下内容:

struct  VideoAnnotation : Comparable , Equatable {
   let content: String
  让imageName: String ?
  让偏移量:TimeInterval

  初始化(内容:字符串,偏移量:TimeInterval,图像名称:字符串?= nil){
     self .content = content
     self .offset = offset
     self .imageName = imageName 
  }

  static  func  < ( lhs : VideoAnnotation , rhs : VideoAnnotation ) -> Bool {
     return lhs.offset < rhs.offset
  }

  static  func  == ( lhs : VideoAnnotation , rhs : VideoAnnotation ) -> Bool {
     return lhs.content == rhs.content && lhs.offset == rhs.offset
  }
}

VideoAnnotation具有三个属性:

  • content是用户看到的字符串标题。
  • imageName是注释图像名称。这是可选的。
  • offsetTimeInterval应显示注释的秒数。

VideoAnnotation符合Comparable并且Equatable因为您需要比较注释以确定要显示的注释,稍后您将看到。

最后,在比较注释时实现要使用的<运算符 from 。此外,您还实现了操作符 from ,您可以在其中指定两个注释在匹配时相等。Comparable``offset``==``Equatable``content offset

取消注释VideoAnnotation下方的注释struct并查看sampleAnnotations您将使用的预定义注释数组。

每个定义都与此类似:

VideoAnnotation (content: "Welcome!" , offset: 5 , imageName: "an-1" )

注意:您可以在**Annotation Assets子文件夹 中查看资产目录中的图像。

接下来,您将更新VideoMatchView以显示注释。

显示同步的注解

首先VideoAnnotation返回VideoMatchView.

打开MatchingHelper.swift并将以下属性添加到类中:

typealias  MatchWithContentHandler  =  
  (( SHMatchedMediaItem ?, VideoAnnotation ?, Error ?) -> Void )
 private  var matchWithContentHandler: MatchWithContentHandler ?
私有 变量lastMatch:SHMatchedMediaItem?
私有 变量lastAnnotationMatch: VideoAnnotation ?

matchWithContentHandler是一个类似于 的处理程序块matchHandler,但它需要一个额外的参数VideoAnnotationlastMatch存储最后匹配的音频元数据并lastAnnotationMatch存储最后匹配的注释。

然后,在类初始值设定项下方,添加:

初始化(matchWithContentHandler 处理程序:MatchWithContentHandler?){
  matchWithContentHandler =处理程序
}

这是另一个设置matchWithContentHandler.

注意:通过将matchHandler和都声明matchWithContentHandler为私有成员并为每个成员创建一个单独的类初始化程序,您可以确保委托方法只设置和调用一个。

接下来,您需要更新SHSessionDelegate以调用matchWithContentHandler.

将以下内容附加到块session(_:didFind:)内的末尾DispatchQueue

if  let handler =  self .matchWithContentHandler {
   let matchingAnnotation =  VideoAnnotation 
    .sampleAnnotations.last { 注释在
      (match.mediaItems.first ? .predictedCurrentMatchOffset ??  0 ) > 
        注释.offset
  }

  if match.mediaItems.first !=  self .lastMatch 
     || 匹配注释!= 自我.lastAnnotationMatch {
    处理程序(match.mediaItems.first,matchedAnnotation ,nil)
    自我.lastMatch = match.mediaItems.first
     self.lastAnnotationMatch = matchedAnnotation
  }
}

每当SHSession打电话给session(_:didFind:)你:

  • 通过将每个注释的偏移量与SHMatchedMediaItem's进行比较来找到正确的注释predictedCurrentMatchOffset,这是预测的当前播放位置。
  • 每当匹配的音频或匹配的注释发生变化时,调用并matchWithContentHandler更新到最近的匹配。lastMatch``lastAnnotationMatch

根据自定义匹配的ShazamKit WWDC 会话session(_:didFind:),ShazamKit 可以多次调用相同的匹配。因此,您只想在收到新匹配时更新您的处理程序。

注意:之前,当你MatchingHelper在 中匹配音乐时SongMatchView,你stopListening()在调用 之后调用matchHandler,如下所示:

if  let handler =  self .matchHandler {
  处理程序(match.mediaItems.first,nil)
  自我.stopListening()
}

那是因为您只需要歌曲的元数据。此处您不调用stopListening(),因为您希望 ShazamKit 继续收听并匹配predictedCurrentMatchOffset当前所在的曲目。

接下来,将以下内容附加到session(_:didNotFindMatchFor:error:), 再次在DispatchQueue块内:

if  let handler =  self .matchWithContentHandler {
  处理程序(零,零,错误)
  自我.stopListening()
}

当没有匹配或有任何其他错误时,您调用matchWithContentHandler传递错误。然后您调用stopListening()以停止匹配过程。

最后,您将更新VideoMatchView以显示注释。

VideoMatchView.swift中,将以下内容替换为onAppear(perform:)

如果匹配器==  nil {
  matcher =  MatchingHelper (matchWithContentHandler: videoMatched)
}

在这里,您调用MatchingHelper的新初始化程序来设置matchWithContentHandler

现在,替换VideoMatchView.videoMatched(result:error:)为:

func  videoMatched
  结果:SHMatchedMediaItem?, 
  注释:VideoAnnotation?, 
  错误:错误?
) {
  如果错误!=  nil {
    status =  "无法匹配音频:(" 
    print ( String (描述: error.debugDescription))
  }其他{
    课程=结果?.title ?? 课程
    情节=结果?.副标题??插曲
    作者=结果?.艺术家??作者

    annotationImageName =注释?.imageName ?? 注释图像名称
    注释内容=注释?.内容?? 注释内容

    print ( "匹配更新:\(String(描述:annotationContent)) " )
  }
}

在这里,您添加注释参数。您还可以设置注释的图像名称annotationImageNameannotationContent标题。

是时候测试应用程序了。

测试应用程序

您终于准备好测试新功能了。构建并运行。然后切换到视频内容

12.png

播放 SwiftUI 课程介绍视频,然后点击Start Episode

首先,应用程序将识别视频并显示第一个注释:

13.png

然后,在00:14,应用程序将显示:

14.png

接下来,在00:47,应用程序将显示:

15.png

观看整个视频。别作弊!当你走到最后,回到中间,注意应用程序如何显示正确的注释。

结论

本教程的最终项目资料下载地址

链接:pan.baidu.com/s/1zcrBA_9d…

提取码:r7z2

在本教程中,您了解了 ShazamKit 和 Shazam 的音频匹配过程。在此过程中,您还学习了如何:

  • 使用 Shazam 目录识别流行音乐。
  • 创建自定义目录并匹配您自己的音频。
  • 将应用内容与播放的音频同步。

这里也推荐一些面试相关的内容!