在本教程中,您将:
- 了解 Shazam 的识别机制。
- 创建 DevCompanion ,一个简单的 Shazam片段,与流行的、已发布的音乐和歌曲相匹配。
- 匹配视频中的自定义音频。
- 可见视频播放位置更改应用内容。
如果你不是,请不要担心。只需要在笔记本电脑上播放首首歌曲,就问 Siri:“这首歌是什么本?”或下载Shazam 应用程序。
入门
01.pngDevCompanion 有两个视图:
- 在什么?:用户可以在其中匹配流行音乐,就像 Shazam 一样。
- 视频内容:用户可以在 raywenderlich.com 上观看 SwiftUI 视频课程时查看注释和其他内容。
打开MatchingHelper.swift并查看代码。这是一个空的帮助程序类,您将在其中编写 ShazamKit 识别代码。
现在不要担心其他文件。创建自定义音频体验时,您将在本教程后面看到您。现在,您将了解更多关于 Shazam 如何识别和匹配音频的信息。
注意:对于本教程,您的 Xcode 13 和运行 iOS 13 和运行 iOS 1。
您还需要一个 Apple 开发帐户人员使用 ShazamKit 应用程序服务配置应用程序 ID。
了解Shazam的匹配机制
在编写代码和使用 ShazamKit API 之前,必须了解 Shazam 如何在幕后工作。
使用 Shaza 时,可以在播放时点击显示大识别Shazam。立即找到该应用程序会听几首歌曲,然后在您的匹配项中播放歌曲信息。您可以匹配的任何部分。
这就是引擎盖下的内容:
- 该应用程序使用实例具有预定义程序的开始形式的流。
- Shazam 库(现在称为 ShazamKit 从应用程序展示的签名签名)。
- 然后,ShazamKit 会将这个音频签名的查询请求发送到 Shazam API。Shazam 服务将签名与 Shazam 目录中流行音乐的签名进行匹配。
- 如果,API 给排序的 ShazamKit 的元数据匹配返回。
- ShazamKit 调用传递元数据的正确委托。
- 结果,由应用程序逻辑来显示轨迹信息。
,您将了解有关 Shazam 签名和目录的更多信息。
Shazam签名
Shazam通过生成高随后的部分的图创建签名,或者是雷声和识别的部分。
签名对原始音频不观看,以确保原始音频的隐私。
在此过程中,Shazam 将应用程序发送的查询签名与参考签名进行匹配。参考签名是从整首歌曲或曲目生成的。
例如,可以识别出大部分的Shazam应用程序在不同的背景下都能获得匹配。
和索引,他们因为更多的占用空间比原始音频小。
您可以在 Shazam 创始人 Avery Wang 的个人研究论文中了解更多关于 Shazam 算法的信息。
,您将探索 Shazam 目录。
Shazam目录
如前所述,Shazam 将签名参考签名进行匹配。
02.pngShazam 目录包含几乎所有流行歌曲的参考签名和元数据。您还可以在应用程序中本地创建自定义目录,为您存储音轨并参考签名和数据。您将在本教程后面创建定义目录。
理论到此为止。接下来,您将学习如何让应用识别流行音乐。
将音乐与 Shazam 的目录相匹配
MatchingHelper.swift并代码:
导入AVFAudio
进口基金会导入
ShazamKit
类MatchingHelper : 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 会话。 -
audioEngine
:AVAudioEngine
您将用于从麦克风捕获音频的实例。 -
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
如果要与自定义目录匹配,它需要一个可选的类型参数。
看看每一步:
-
首先,
SHSession
如果您使用自定义目录,则创建一个目录并将其传递给它。SHSession
如果您不提供目录,则默认为 Shazam 目录,该目录适用于应用程序的第一部分。 -
您设置
SHSession
委托,稍后您将实现它。 -
您调用
AVAudioEngine
'sAVAudioNode.installTap(onBus:bufferSize:format:block:)
,这是一种准备音频输入节点的方法。在传递捕获的音频缓冲区的回调中,您调用SHSession.matchStreamingBuffer(_:at:)
. 这会将缓冲区中的音频转换为 Shazam 签名,并与所选目录中的参考签名进行匹配。 -
您将
AVAudioSession
类别或模式设置为录制。AVAudioSession
然后,您在应用程序第一次运行时通过调用'srequestRecordPermission(_:)
向用户询问 麦克风权限来请求麦克风录音权限。最后,您通过调用 开始录制
AVAudioEngine.start()
。
注意:NSMicrophoneUsageDescription已经在项目的Info.plist 中设置。
matchStreamingBuffer(_:at:)
处理捕获音频并将其传递给 ShazamKit。或者,您可以使用SHSignatureGenerator
生成签名对象并将其传递给match
of 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
是完成匹配时调用的方法。它:
- 设置
isListening
为false
。因此,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 的对象,SHCustomCatalog
ShazamKit 为自定义目录提供的类型。这是一个静态方法,用于初始化您的自定义目录并返回它。在这里,它:
- 检查应用程序包中的 Shazam 签名文件DevCompanion.shazamsignature。如果文件不存在,则返回 nil。
- 读取
Data
签名文件的内容并初始化refSignature
,这是一个SHSignature
ShazamKit 用于存储签名数据的容器类型。 - 定义
videoMetadata
,SwiftUI 课程介绍视频的元数据。这是SHMediaItem
具有一些预定义属性的。 - 初始化目录,然后调用
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())
在这里,您将自定义目录传递给MatchingHelper
并SHSession
在下一场比赛中使用它。现在,您已准备好进行测试。
打开 SwiftUI 课程介绍并播放视频。构建并运行。切换到视频内容选项卡并将手机靠近扬声器,以便它可以听到视频的配乐。
09.png现在,点击开始剧集。几秒钟后,您将在顶部看到视频信息:
10.png该应用程序匹配您自定义目录中的音频!
您还可以将自定义目录保存为不透明文件,就像使用SHCustomCatalog.write(to:)
. 此文件具有扩展名.shazamcatalog。要了解更多信息,请查看Apple 文档。
注意:根据自定义目录匹配音频与匹配 Shazam 目录没有什么不同,只是ShazamKit在您的设备上进行本地匹配并且不必与 Shazam 的服务器通信。
注意:您也可以使用以下步骤创建自己的.shazamsignature文件:
- 开始捕获音频
AVAudioEngine
- 与您之前所做的相同。 - 在
AVAudioNode.installTap(onBus:bufferSize:format:block:)
, callSHSignatureGenerator
的回调中,从回调参数中append(_:at:)
传递buffer
and 。audioTime
这将从捕获的音频中生成一个签名。 - 曲目结束时停止录制。
- 写入
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
是注释图像名称。这是可选的。 -
offset
是TimeInterval
应显示注释的秒数。
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
,但它需要一个额外的参数VideoAnnotation
。lastMatch
存储最后匹配的音频元数据并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)) " )
}
}
在这里,您添加注释参数。您还可以设置注释的图像名称annotationImageName
和annotationContent
标题。
是时候测试应用程序了。
测试应用程序
您终于准备好测试新功能了。构建并运行。然后切换到视频内容。
12.png播放 SwiftUI 课程介绍视频,然后点击Start Episode。
首先,应用程序将识别视频并显示第一个注释:
13.png然后,在00:14,应用程序将显示:
14.png接下来,在00:47,应用程序将显示:
15.png观看整个视频。别作弊!当你走到最后,回到中间,注意应用程序如何显示正确的注释。
结论
本教程的最终项目资料下载地址
链接:https://pan.baidu.com/s/1zcrBA_9d4FA6ysil-9cNPw
提取码:r7z2
在本教程中,您了解了 ShazamKit 和 Shazam 的音频匹配过程。在此过程中,您还学习了如何:
- 使用 Shazam 目录识别流行音乐。
- 创建自定义目录并匹配您自己的音频。
- 将应用内容与播放的音频同步。
这里也推荐一些面试相关的内容,祝各位网友都能拿到满意offer!
GCD面试要点
block面试要点
Runtime面试要点
RunLoop面试要点
内存管理面试要点
MVC、MVVM面试要点
网络性能优化面试要点
网络编程面试要点
KVC&KVO面试要点
数据存储面试要点
混编技术面试要点
设计模式面试要点
UI面试要点
网友评论