JavaScript 中的声音活动识别

2025-05-24

JavaScript 中的声音活动识别

对于我的个人项目,我经常从阅读的有关人机交互的研究论文中获得灵感。

最近,我一直在研究一种名为“ Ubicoustics - 即插即用声学活动识别”的技术,它是由美国 CMU(卡内基梅隆大学)的研究团队开发的。

声学活动识别利用声音的丰富特性来深入了解环境或活动。

这可用于增强智能系统并构建更加个性化的互联家居。

CMU 的研究人员使用 Python 制作了他们的实验原型,并将他们的项目开源到 Github 上,如果你想看看的话。但我想看看是否可以使用 Web 技术复现类似的功能,结果成功了!😃

最终结果是一个基于浏览器的声学活动识别系统的原型,可以对说话、咳嗽、打字、刷牙和手机铃声进行分类:

使用麦克风进行声音活动识别

我的探索还处于早期阶段,但我想分享我迄今为止学到的知识。

为什么要使用声音?

我们身边的很多设备都内置了麦克风;比如笔记本电脑、手机、平板电脑、智能手表、家庭助理等等……然而,它们并没有真正利用声音的丰富属性。
通常情况下,应用程序会监听某个词来触发诸如“Ok,Google”或“Alexa”之类的操作,但词并非唯一能产生可辨别声音的东西;我们周围的一切都会产生声音。

如果你花一点时间想一想,你就会知道雨的声音是什么,你知道打开冰箱和微波炉时的声音有什么区别,你能认出门铃的声音,即使它不是你的,等等......

我喜欢这样想:如果你的大脑能够接受声音输入并对其进行分类,那么使用机器学习也应该可以实现类似的事情;所以让我们看看它是如何工作的。

技术栈

对于这个原型,我使用Web Audio API将麦克风作为输入,使用Canvas用声音数据构建频谱图,并使用Tensorflow.js训练模型来识别活动。

为了使其更容易,我使用了Google 的Teachable 机器实验来录制我的声音样本,训练机器学习模型并将其导出。

现在,让我们来看看我构建它所采取的一些步骤。

可视化声音数据

当您使用 Web Audio API 检查从麦克风输入获取的数据时,您会得到如下内容:

声音数据以整数数组形式记录在控制台中

从这个角度来看,作为数字数组,我们很难找到任何特定的模式来区分拍手和打响指。

为了帮助我们,我们通常会将这些数据可视化。两种标准方法是将其转换为波形图或频率条形图,如下所示:

将声音输入的数据可视化为波形和频率条形图

波形表示声波随时间变化的位移。
声音是空气分子的振动,这张图显示的是声波的振荡。但是,即使通过这种方式进行可视化,我们仍然无法得出任何结论。

频率条形图展示了声音数据,衡量了波形在给定时间内重复的次数。
通过这种可视化方式,我们或许可以开始获得一些见解,识别出某种“节拍”,但我们还远未达到那种程度。

表示这些数据以找到模式的更好方法是所谓的频谱图

频谱图是信号频率随时间变化的频谱的直观表示。你可以把它想象成声音的热图。

使用 Canvas 将我的麦克风输入可视化为声谱图,我可以很容易地识别说话和拍手之间的区别。

声谱图显示了说话和拍手之间的区别

到目前为止,这些都没有用到机器学习。我只是用了 Web Audio API 从麦克风获取数据,然后用 Canvas 将其转换成声谱图。

现在我们可以观察到某些活动产生的数据“看起来”不同,我们可以继续使用机器学习和 Tensorflow.js 来构建分类模型。

使用机器学习对声音数据进行分类

如上所述,为了使其更容易,我使用 Teachable 机器实验来记录我的声音样本,运行训练并生成模型。

到目前为止,我的主要目标是验证我的想法是否可行,所以我更喜欢使用已经构建好的东西,但是,你绝对可以从头开始创建自己的声音分类系统(我希望这是我潜在的下一步之一)。

目前,我的训练过程如下:

使用声音样本训练可教机器

首先,你需要录制20秒的背景噪音。这是必要的步骤,这样算法才能识别出你没有进行任何活动时的某种中性状态。

然后,您可以添加不同的“类别”,即不同的活动。每个活动至少需要记录 8 个样本,但越多越好。

在上面的例子中,我只记录了弹指的样本,然后运行训练并在最后实时检查预测结果。
根据你想要构建的内容,你可能会添加更多类别,但检查预测是否准确非常重要,这样你就可以记录更多样本,并在必要时重新训练。

如果您对输出感到满意,您可以下载该模型并将其用于您的项目中。

使用机器学习模型

一旦训练过程完成,您就可以使用生成的模型对以前从未“见过”的新声音样本进行一些实时预测。

为此,您需要首先导入框架和另一个模型:

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js">
</script>

<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/speech-commands@0.4.0/dist/speech-commands.min.js">
</script>
Enter fullscreen mode Exit fullscreen mode

在上面的代码示例中,我们导入了 Tensorflow.js 和语音命令模型

我们需要这样做,因为我们预测新声音样本的方式是使用迁移学习

迁移学习意味着我们使用针对特定输入进行优化的预训练模型,向其中添加我们自己的样本并重新训练所有内容。

语音命令模型是 Tensorflow.js 中唯一一个使用声音样本进行训练的预训练模型。
它针对语音单词的分类进行了优化,但我想看看它在输入活动的声音样本后是否仍然准确。

导入工具后,您需要加载自定义模型:

let model;

async function setupModel(URL, predictionCB) {
   //store the prediction and audio callback functions
   predictionCallback = predictionCB;

   const modelURL = 'model.json';
   const metadataURL = 'metadata.json';
   model = window.speechCommands.create('BROWSER_FFT', undefined, modelURL, metadataURL);
   await model.ensureModelLoaded();

   const modelParameters = {
       invokeCallbackOnNoiseAndUnknown: true, // run even when only background noise is detected
       includeSpectrogram: true, // give us access to numerical audio data
       overlapFactor: 0.5 // how often per second to sample audio, 0.5 means twice per second
   };

   model.listen(
       //This callback function is invoked each time the model has a prediction.
       prediction => {
           predictionCallback(prediction.scores);
       },
       modelParameters
   );
}
Enter fullscreen mode Exit fullscreen mode

从 Teachable Machine 下载模型后,您会获得一个model.json和两个metadata.json文件。这两个文件都需要用到才能正常工作。metadata.json 文件包含有关类名等信息……

然后,您需要调用speechCommands模型并将模型变量传递给它。

模型加载后,您可以定义一些额外的参数,调用该listen方法,每次从来自麦克风的实时音频数据中预测某些内容时都会触发回调。

一旦设置了函数,就可以这样调用它:

let labels = ["Clapping","Speaking","_background_noise_"];

setupModel(URL, data => {
     // data will look like this [0.87689, 0.21456, 0.56789]
      switch(Math.max(...data)){
               case data[0]:
                   currentPrediction = labels[0];
                   break;
               case data[1]:
                   currentPrediction = labels[1];
                   break;
               default:
                   currentPrediction = "";
                   break;
           }
       }
        return currentPrediction;
});
Enter fullscreen mode Exit fullscreen mode

我定义了一个包含我训练过的类别的数组,当发生预测时,结果将以 0 到 1 之间的浮点数数组的形式返回,表示每个类别被预测的概率;如果最大数字是概率数组中的第一个,那么我们识别的活动将是上面定义的标签数组中的第一个。

演示

最后,我的原型看起来像这样:

说话、咳嗽和刷牙之间的活动分类

如果您想亲自尝试一下,这里是演示的链接

我在安静的环境中测试会更准确,因为我的样本是在家里录制的。如果在火车或咖啡馆测试,背景噪音与训练时的背景噪音差别太大,准确率会下降。

目前,由于时间限制,它主要针对桌面版 Chrome 进行了优化。为了使其在其他浏览器和移动设备上也能正常运行,还需要修复一些问题。😞

应用

目前,该原型还只是探索性的,但我相信这种技术具有潜力。

我们不用购买多个昂贵的智能设备,例如冰箱、咖啡机和微波炉,这些设备只能知道自己在做什么(智能冰箱不知道咖啡机是否打开了,等等),而是可以用一个具有更多情境理解能力的设备来代替它们,不仅可以理解其他设备,还可以理解设备所在的房间以及用户的活动。

这可能对以下应用程序有帮助。

情境感知视频服务

烹饪

如果你一边做饭一边跟着 YouTube 上的菜谱做菜,当你需要切蔬菜、用微波炉加热一分钟、使用打蛋器等等时,视频会自动暂停,通过监听你的动作。这样,你就不用在做饭时在笔记本电脑、平板电脑或手机之间来回切换了。

观看你最喜欢的电视剧

如果您正在观看 Netflix,这时您的手机或门铃响了,视频可能会暂停,而您无需寻找遥控器,因为门铃或电话响起通常意味着您将离开电视几分钟。

互动故事讲述

如果你在创意机构或媒体公司工作,线上内容的互动性至关重要,那么这类技术或许能带来一种更具互动性和娱乐性的内容消费方式。通过让你以不同的方式参与其中,比如拍手、模仿声音等等,故事的沉浸感会大大增强。

健康追踪

正如您在我的快速演示中看到的,您可以对咳嗽和刷牙的声音进行分类,因此您还可以训练您的系统识别打喷嚏、打鼾等......并建立某种健康跟踪系统。

肯定还有更多的应用程序,但这只是为了让您了解它可以在哪里使用。

限制

主要限制之一在于隐私问题。你肯定不希望你的 Google Home 或 Amazon Alexa 不仅监听你的对话,还能通过监听你的所有活动来了解你的一举一动吧……对吧?!😢

有一种方法可以构建您自己的私人离线系统,但这绝对不是大多数人可以访问的。

目前另一个主要限制是无法同时理解多项活动。如果你在刷牙时有人和你说话,这个系统一次只能预测一项活动。

然而,这正是另一个令人兴奋的项目发挥作用的地方,它被称为“通用合成传感器”😍,接下来我将简要讨论一下。

后续步骤Next steps

我还有很多东西要学,我希望有时间在 2020 年探索这个领域,但我的下一步是构建通用合成传感器

卡内基梅隆大学的研究人员不仅使用声音数据来识别活动,还致力于开发一个集成多个传感器(麦克风、温度传感器、加速度计、运动传感器、光传感器等)的小型设备,以组合多个频谱图,从而监控更大的环境并构建更强大的活动识别系统。

带有频谱图的通用合成传感器


现在就这样了!

我知道人们可能会对这个实验持怀疑态度,特别是在 JavaScript 方面,但我知道这个实验不需要硬件升级,这意味着我们正在等待的主要事情可能是找到正确的应用程序。

就我个人而言,我总是非常高兴地知道,作为开发人员,我们可以通过使用 JavaScript 构建原型来参与此类研究,并探索交互的未来。

希望有帮助!🙂

文章来源:https://dev.to/devdevcharlie/acoustic-activity-recognition-in-javascript-2go4
PREV
使用手势在 Figma 中构建 UI
NEXT
Flutter 开发者的十大 YouTube 频道(2020 年)总结