大多数浏览器和
Developer App 均支持流媒体播放。
-
探索 SoundAnalysis 中内置的声音分类
探索如何在您的 app 中使用 Sound Analysis 框架来检测和分类来自任何音频源的离散声音,包括来自麦克风的现场声音或来自视频音频文件的声音,并在声音发出的瞬间精确识别。了解内置声音分类器如何让您轻松识别 300 多种不同类型的声音,而无需自定义的受训模型。包括人声、乐器、动物和各种物品的各种声音。对于自定义模型,请参阅如何利用 Audio Feature Print 功能提取器创建具有可变声音窗口控制的较小模型,以更好地满足您 app 的用途。有关声音分类和 Sound Analysis 框架的更多信息,请观看 WWDC19 中的“在 Create ML 中训练声音分类模型”。
资源
相关视频
WWDC22
WWDC21
WWDC19
-
下载
♪ ♪ 嗨 欢迎来到WWDC的音频分析专题讲座 我是乔恩. 黄 我是音频团队的研究员 今天我和我的同事凯文 会介绍声音分类的改进 这都是有赖于Sound Analysis框架 和CreateML才能达成 2019年 我们让大家能 用CreateML训练声音分类模型 我们展示创建声音分类模型 并部署到Apple设备的过程有多简单 当你使用这个框架 所有的计算 都经过硬件加速的优化 且在本地设备上完成 这能帮助维护你的用户的隐私 因为音频从不会传到云端 我们利用Sound Analysis框架导入 叫做声音识别的辅助功能 这个功能可以在 从环境中听到特定声音时 向用户发送通知 像是警报声 宠物的声音 还有其他生活常见声音 这只是声音分类的一种应用 我们来看看还能用来做什么 演示应用程序正在用Mac的 内置麦克风 聆听环境中的声音 它将音频传送至声音分类器 并在UI中 显示分类的结果 所以在我和你聊天的同时 它检测到语音 请和我一起休息一下 看看会发生什么事 不用拘束 我们先放点音乐 嘿Siri 播放Karun和Mombru的 《Catch a Vibe》 现在播放Karun和Mombru的 《Catch a Vibe》 ♪ ♪ ♪噢♪ 注意分类器分别检测到 音乐和唱歌的声音 ♪我不认识任何人♪ ♪感觉那么对味♪ ♪不认识任何人会让我♪ ♪有感觉 感受到频率…♪ 现在请和我一起喝个茶 ♪感觉不错 宝贝♪ ♪我们能看到♪ ♪若我们是对的♪ ♪是你微笑的样子♪ ♪屏住呼吸 宝贝 我们能♪ ♪有感觉 感受到频率♪ ♪有感觉 只有你和我♪ ♪感觉不错 宝贝 我们能看见♪ ♪若我们能♪ ♪我说♪ ♪那是我的一部分♪ ♪你看到的所有艺术♪ ♪你应该骄傲…♪ 这茶很好喝 ♪你是我的宝贝♪ ♪我看到你很努力…♪ ♪怎么会这样?♪ ♪怎么会这样?♪ 嘿Siri 停止播放 如果你假定我为这些声音类别 分别收集了一些数据 并用CreateML训练了定制模型 你会那样想很合理 对 我可以那样做 但事实上刚刚用的分类器是内置的 今年新推出的 我们把声音分类器 直接内置在Sound Analysis框架中 现在比以往都更容易 在你的应用程序里启用声音分类 所有平台都支持
内置分类器的重点就是简化 开发者体验 它不需要收集和标签 大量数据 专门的机器学习和音频专业 还有大量算力 不须那些就能开发高准确度模型 你花越少时间烦恼这些细节 就能花更多时间 让你的应用程序的用户体验更丰富 只需要几行代码 就能启用声音分类 我会示范这个分类器可以做什么 有超过300个可用的类别 我们来仔细瞧一瞧 我们可以分类家畜、牲畜 和野生动物的声音
至于音乐 它可以识别很多种乐器: 键盘乐器、打击乐器 弦乐器、管乐器 我们可以检测不同的人类声音: 团体活动 呼吸声、发声
然后还有东西的声音 像是车辆 警报、工具、液体 还有好多 这些即用类别你都可以尝试 我要把画面交给凯文 请他介绍如何使用这个声音分类器 谢谢乔恩 嗨 我是凯文 音频团队的软件工程师 我想通过我打造的小应用程序 向你示范如何使用 新的内置声音分类器 我原本希望乔恩能示范 分类器分辨牛铃的效果多好 但因为牛铃不适合他的演示 我想到另一个点子 我的Mac上有一些 我为这场专题讲座准备时 收集的媒体 而且我很确定 我有些内含牛铃的旧片段镜头 我很想给你看 但我得先找到它 这代表我必须找到对的文件 然后我必须打开来看 找到对的片段 所以我要怎么做到? 我会写一个简单的程序 让它用内置声音分类器 读取一个文件并告诉我 里面是否有某个特定的声音 如果它找到那个声音 程序可以用分类器 告诉我声音出现的时间
我可以接着用Shortcuts 现在可以在macOS使用 创建一个工作流 让我的程序浏览很多文件 当我的程序找到声音 工作流可以自动 利用报告的检测时间 提取含有那个声音的视频片段 这很适合寻找牛铃片段
我们来看看它的实际运作
我在这里有一个充满视频的文件夹
我会选择所有文件 并用Quick Actions菜单启动快捷方式
它叫我选择我想找到的声音 所以我会从选项列表中选择牛铃
现在我的快捷方式正在运行 稍待片刻后 它很快找到我想找的声音 并以访达窗口展示给我看 我们看看 看起来不错 乔恩 我们来详细检视我刚用的快捷方式
我的快捷方式开始时 它会收集它能认出的所有声音 并做成清单 请我选一个 它用我的选择造访每个 我在访达中选择的文件 并找找看里面有没有那个声音 检测到我的声音时 它会从视频提取 声音发生的前后几秒 并向我展示那个片段 在这些步骤中 有两个步骤 会用到内置分类器 这些是我在我的自定应用程序中 实施的步骤 让Shortcuts能按需使用
虽然我不会深入介绍Shortcuts 若你想了解更多 请参考WWDC专题讲座 标题为 《Meet Shortcuts for macOS》
现在我们来看看 我的应用程序的两个定制操作 第一个操作报告应用程序可以识别的 所有声音 因为应用程序使用内置声音分类器 它可以识别几百种声音 这是我写来取得这些声音的函数 我用新的初始值设定项 创建了一个SNClassifySoundRequest 它让我能选择内置分类器 有了这个请求后 我可以用它来查询 分类器支持的清单上的声音 应用程序的第二个操作 告诉Shortcuts 声音是在文件中的什么时间出现 要执行这点 如果有检测到声音的话 我会进行声音分类 并报告第一次检测到声音的时间 要进行声音分类 我需要准备三个东西 第一 我需要一个 SNClassifySoundRequest 我可以用它来配置声音分类 第二 我需要一个 SNAudioFileAnalyzer 它能让我将分类 锁定在特定的文件 第三个点 需要额外注意 我需要定义自己的Observer类型 它会处理分类的结果 先跳过Observer 这是准备前两个对象的代码
我可以用内置分类器 创建SNClassifySoundRequest 然后我可以用想分类的文件的URL 创建SNAudioFileAnalyzer 如果此时我已经准备好Observer 那可以轻松开始进行声音分类 但还缺少一小部分,就是定义Observer 所以我们来完成它吧 我在这里用一个空的Observer开始 它从NSObject继承 并遵从SNResultsObserving协议 我会用我想搜寻的声音标签 初始化实例 然后我会添加一个CMTime会员变量 存储检测到声音的时间 我只需要执行这个请求: didProduce result method 这个方法会在 声音分类有结果时被调用 所以我预期收到 SNClassificationResult的实例 我可以用结果的 classificationForIdentifier 方法提取 我找的标签的信息 我会查询标签的置信度分数 若分数超越特定的阀值 我会判断声音被检测到 当我注意到第一次检测到的时间 我会保留声音发生的时间 让我可以晚点提供给Shortcuts
这样我的Observer就完成了 我有所有必需要素 能够判断文件里是否有某种声音 这个例子提到两个 我想进一步讨论的重要主题 第一 我会谈检测的时间 然后我会谈检测阀值
我们先讲检测的时间 分类音频时 信号会被切成重叠的窗口 每一个窗口 你都会获得一个结果 告诉你检测到什么声音 还有置信度 你也会获得一个时间范围 它会告诉你 哪部分的音频被分类 在我的应用程序中 当我检测到声音 我用结果的时间范围 判断声音在什么时候出现 但当窗口的时长改变时 时间范围可能被影响 你可以定制窗口时长 根据你的用例 让它更长或更短
短的窗口很适合用在短的声音 像是打鼓声 这是因为你可以在短的一段时间里 捕获那个声音的 所有重要特色 短的窗口不会切掉 任何重要信息 用短窗口时长的优点 是它让你能更准确地找到 声音出现的那一刻
但短窗口时长可能不适合 用在较长的声音上 例如警报器 可能在较长的时间内 包含上升和下降的音高 在一个窗口内捕获所有音高 能帮助声音分类 正确检测声音 一般来说 窗口时长应该够长 才能捕获你有兴趣的声音的 所有重要部分 如果你想编辑窗口时长 你可以设定SNClassifySoundRequest的 windowDuration属性 但要注意 不是所有窗口时长都支持
不同的分类器可能支持 不同的窗口时长 若想查看哪些窗口时长获得支持 可以读SNClassifySoundRequest的 windowDurationConstraint 内置分类器支持的窗口时长 在半秒到15秒之间 你的应用程序采用分类器时 一秒或更长的时长 是很好的起始点
我们接着来谈置信度阀值 我的应用程序中 只要声音的置信度上升超过 固定的阀值 我就认定检测到了声音 我将阀值设为0.5 但在为你自己的应用程序 选择阀值时 有几点要考虑 分类器可以同时检测 多种声音 当这发生时 你可能会注意到 有好几个置信度高的标签分数
和使用CreateML训练的 定制模型不同 标签分数加起来 并不会等于一 置信度都是独立的 不应该相互比较
因为置信度分数都是独立的 为不同的声音设定不同的置信度阀值 可能会有帮助 选择阀值需要折衷 较高置信度阀值能降低 错误检测到声音的概率 但它也会让 因为不够强而错过真实检测的 概率上升 为你的应用程序选择阀值时 你需要找到一个值 能为你的用例在这些因素中找到平衡 注意 当你设定一个定制窗口时长 置信度分数可能改变 所以这也可能影响你的阀值 最后一件 使用内置分类器时需要注意的事 就是有些声音很相似 在分类器可以辨别的大量声音中 有几组声音 单靠音频可能很难分辨 就连对人类也是 若可能 最好谨慎筛选 你要注意哪些声音 你应该尽量只找 你的应用程序的使用情境中 很有可能出现的声音 说到这 我们把画面交还给乔恩 了解CreateML有什么新的 关于声音分类的内容 谢谢凯文 那个范例很棒 我很高兴你喜欢那段牛铃视频 现在让我展示 CreateML有什么新的改进 或是更特定地说 你可以如何利用内置分类器的力量 改进你的定制模型 我们用一大堆数据训练内置分类器 数据来自广大数量的类型 所以模型里有很多 关于声音分类的知识 这些知识可应用于 用CreateML训练你的定制模型时 让我向你展示它的作用方式 声音分类器可被分为 两个不同的网络 第一个部分是特征提取器 第二部分是分类器模型 特征提取器 有时称为嵌入模型 是这个网络的中枢 它将音频波形转化成 低维度空间 良好训练的特征提取器 将听觉上类似的声音 放在空间里的附近位置
例如 吉他声会聚集一起 但放在远离鼓声和车声的地方
管道的第二部分 是分类器模型 它接受特征提取器的输出 并运算分类概率 分类器会受益于 和好的特征提取器配对 像是我们嵌入至内置分类器的这个
我们开放内置分类器的 特征提取器供你使用 它叫Audio Feature Print 当你在CreateML里训练你的自定模型 你的模型会 和Audio Feature Print配对 这样你的模型能受益于 内置分类器所含的所有知识 和前一代特征提取器相比 Audio Feature Print 有了全方面的改进 虽然这个网络更小更快 与所有我们比较的对标数据集相比 它的准确度都比较高 就像内置分类器 使用Audio Feature Print的模型 支持弹性的窗口时长 你可以选择长窗口时长 为警报这类的声音优化 或是为鼓声这类较短的声音 选择短窗口时长 用CreateML训练你的定制模型时 Audio Feature Print 是新的默认特征提取器
窗口时长是训练时 用来生成单一特征的音频长度 它的默认值是三秒 但你可以依据需求调整 CreateML让你能选择 半秒至15秒之间的窗口时长 若想看训练定制模型更详细的范例 你可以参考2019年WWDC专题讲座 《Training Sound Classification Models in CreateML》 它也示范如何用 Sound Analysis框架 执行定制模型 谢谢你参与 音频分析专题讲座 今天我们介绍了内置于OS的 强大的新声音分类器 除此之外 我们升级了CreateML里的特征提取器 这些会解锁新的可能 我们等不及看到你会怎么把它们 用在你的应用程序 祝你有美好的WWDC [欢快的音乐]
-
-
8:12 - Get list of recognized sounds
func getListOfRecognizedSounds() throws -> [String] { let request = try SNClassifySoundRequest(classifierIdentifier: .version1) return request.knownClassifications }
-
9:19 - Create sound classification request
let request = try SNClassifySoundRequest(classifierIdentifier: .version1) let analyzer = try SNAudioFileAnalyzer(url: url) var observer: SNResultsObserving // TODO try analyzer.add(request, withObserver: observer) analyzer.analyze()
-
9:52 - Implement sound classification observer
class FirstDetectionObserver: NSObject, SNResultsObserving { var firstDetectionTime = CMTime.invalid var label: String init(label: String) { self.label = label } func request(_ request: SNRequest, didProduce result: SNResult) { if let result = result as? SNClassificationResult, let classification = result.classification(forIdentifier: label), classification.confidence > 0.5, firstDetectionTime == CMTime.invalid { firstDetectionTime = result.timeRange.start } } }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。