在美国脱口秀广播中检测重复内容

在Cortico,我们已使谈话广播变得可搜索,以帮助在全国范围内传达代表性不足的声音。 使用谈话广播,我们可以了解当地人在谈论什么。 但是,事实证明,谈话广播中有很多重复的内容,从联合内容(例如,在其所有成员电台播放的NPR片段)到商业广告。 这不仅使我们的搜索空间以及热门术语的结果变得混乱,而且使在全国广播内容下听到本地声音变得更加困难。 因此,我们开始了一段旅程,以了解如何自动检测重复的音频内容。

寻找解决方案

由于我们正在转录所有无线电数据,因此我们已经有了基于文本的重复检测的概念。 但是,基于转录本的重复检测会随转录精度而变化,而转录精度又会随背景噪声而变化。 此外,转录仅限于英语,有时在口音上有困难。 因此,我们想看看是否存在不依赖文本的解决方案,该解决方案可能会补充我们的抄本重复检测。

我们不仅要提高重复检测的准确性,还希望更多地了解谈话广播的状况。 联合广播内容中有多少谈话广播? 是否有广播相同内容的广播电台集群?

音频指纹

我们决定尝试的解决方案是音频指纹识别。 音频指纹识别为我们提供了一种通过散列(“指纹”)识别音频文件部分的方法。 然后可以将此哈希与其他音频文件的其他部分进行比较。 该技术由Shazam发布,看起来像这样:

  1. 使用快速傅立叶变换将音频从时域转换到频域
  2. 查找结果频谱图中的峰,并按时间和频率索引
  3. 计算相对峰位置上的哈希函数,以获取哈希值序列( hash(frequencies of peaks, time diff between peaks)
  4. 识别音频文件之间常见哈希的顺序

对我们来说幸运的是,存在一个用于该技术的开源Python库,称为Dejavu。

就像考虑一样,考虑一下小甜甜布兰妮的歌曲清单。 经过FFT和哈希计算过程后,每首歌曲都有一个哈希以及该哈希的位置。 在原始的Dejavu库中,这些存储在MySQL数据库中。

现在,假设您在广播中听到优美的歌声,而怀旧之情袭来。 您只需要知道这首歌是什么! 使用Shazam之类的应用,您的手机可以对歌曲的出现进行指纹识别(创建哈希序列),然后将该哈希序列与其数据库中的其他哈希序列进行比较。 使用此序列匹配方法,您的电话可以告诉您正在播放的歌曲,无论它从什么时候开始收听歌曲。

在上图中,传入的歌曲似乎是Britney的热门歌曲Toxic! 说到有毒,您是否读过我们关于Twitter对话中可视化毒性的文章? 🙂

有了算法和Python实现,我们着手将音频指纹识别应用于我们的特定问题。 我们的目标是能够说:“在剪辑A中从1:10到2:10,我们拥有与剪辑B中从3:25到4:25相同的内容”。 谈话广播剪辑可以从原始内容开始,然后播放一些重复的广告,然后再回到原始内容。 与Shazam问题不同,我们不想只返回匹配的顶部“歌曲”,而是返回给定剪辑中的所有匹配。 此外,我们需要添加逻辑以确定每个比赛的时间范围。

除了这个细分问题之外,我们还有另一个问题-一个很大的问题! 以下是一些统计信息:

  • 37个州的163个广播电台
  • 每月9.7亿个单词
  • 每月摄取3.5 TB音频

总计为:

  • 每天50,000个指纹文件
  • 每个文件约10,000个指纹

与音乐流匹配不同,我们不会尝试在传入的歌曲和其他所有音频片段之间找到匹配项。 相反,我们希望将每首歌曲与其他每首歌曲进行比较。 这给我们带来了一个n²问题,其中n是给定音频文件中的每个可能序列,乘以50,000! 我们最大的问题很快成为如何扩展此过程。

我们的解决方案

我们可以将规模问题分为两个不同的部分:

  1. 指纹识别(为每个无线电剪辑生成哈希序列)
  2. 匹配

扩展指纹识别过程本身是相对简单的。 由于我们已经有一堆机器正在转录传入的音频数据,因此我们添加了一个过程,可以对进入的文件进行指纹识别,然后将该文件扔到S3中供以后使用。

缩放匹配过程并不是那么简单,因为并不是每个过程都可以并行运行-每个广播片段都必须与其他广播片段进行比较。 我们很快就看到MySQL(带有Dejavu库的默认数据库)不会削减它,因此我们冒险进入Spark领域。 使用Spark,我们可以将所有指纹值保存在许多计算机的内存中,而不是保存在庞大的数据库中,然后在内存中进行比较。 最初的Dejavu代码不是以功能性方式编写的,但是重复检测算法(可能与基因测序最相似)很适合映射简化功能。

有关此匹配算法如何工作的概述,请查看此“可观察的笔记本”,该笔记本可让您使用参数并逐步介绍算法。 请注意,此笔记本是用JavaScript编写的,以便于可视化和共享,但实际实现完全是使用Python。 总体而言,该算法如下所示:

  1. 地图→下载每个指纹文件
  2. 减少→按哈希值分组
  3. 映射→计算匹配哈希之间的偏移量
  4. 减少→对齐匹配的哈希/偏移量对
  5. 地图→获取时间范围匹配
  6. 减少→按单选片段名称分组
  7. 地图→将结果保存回S3

基础设施

尽管我们认为以功能方式重写算法是最困难的,但与将Spark流程部署到我们的基础架构相比,这相对容易一些。 在Cortico,我们通过Amazon EKS使用Kubernetes。 我们希望在过去的24小时数据中每天进行一次重复检测。 在我们理想的世界中,当作业开始时,我们将为Amazon EC2中的集群启动机器,而当作业完成时,机器将关闭。

我们使用附加到Kubernetes集群自动缩放器的EC2自动缩放组实现了这一点(此AWS教程中的更多信息)。 通过将EC2自动伸缩组配置为使用竞价型实例(AWS折扣提供的备用EC2机器),并让Kubernetes集群自动伸缩器告诉AWS我们何时需要这些机器以及何时不再需要这些机器,我们可以在最低成本。 工作流程如下:

  1. Kubernetes cron作业创建X个Spark工作者,全部带有资源请求
 规格: 
副本:10
...
容器:
-名称:spark-worker
...
资源:
要求:
cpu:“ 5”
内存:“ 17Gi”

2. Kubernetes集群自动缩放器检测到它没有足够的资源来创建所有这些Spark Worker,因此向EC2自动缩放组发出警报

3. EC2自动伸缩组会为其所需的竞价型实例竞标数量,并将其作为新节点添加到Kubernetes集群中。

4.新机器启动后,重复检测作业将部署并在这些新机器上运行

5.作业完成后,Kubernetes集群自动缩放器会检测到它有未使用的便笺,并要求EC2自动缩放组放弃它们。

6.每天重复一遍!

结果

统计资料

使用音频指纹进行重复检测似乎很好地补充了我们现有的基于转录本的方法。 指纹识别方法可以找到与基于成绩单的方法相同的大多数片段,以及其他许多片段。 总体而言,指纹识别方法找到了74%的重复方法标记的结果,而47%的方法是基于转录本的方法标记的结果。 听这些剪辑,我们发现指纹方法几乎具有完美的精度,这表明它的影响是严格累加的。

但是,这两种方法不是一对一的,因为我们基于成绩单的方法可以识别重叠的单个句子,并且可以识别何时由不同的说话者说出相同的文本。

对这两种方法的精度和召回率进行更严格的评估需要大量我们尚未进行的手工标记,但是早期迹象很有希望!

音频指纹数据的前几天推出后,我们很兴奋地看到我们的数据是什么样的。

威斯康星州麦迪逊

由于我们在威斯康星州麦迪逊市启动本地语音网络的努力,我们看了可以从麦迪逊市听到的广播电台。

在这张照片中,蓝线代表我们在全国范围内收录的任何其他广播电台的重复内容。 我们可以很清楚地看到WORT的重复内容很少,阅读其Wikipedia页面可以确认它具有很高比例的本地制作内容。 上图恰好显示了一个星期一,但我们可以切换一周中的不同日期,以查看重复内容在周末与工作日之间的变化。

在这里玩可观察的笔记本!

广播电台集群

为了可视化广播台的“集群”,在广播台中,彼此重叠程度高的广播台聚在一起,我们创建了一个力向图。 力向图中的每个节点都是一个无线电台,每个链接代表重复内容的秒数,而较粗的链接意味着更多的重复内容。 由于检测到重复内容的秒数很高,因此出于可视化目的,仅将重复内容的秒数阈值以上的站点显示为“已链接”。

查看此图,我们立即看到两个明显的群集:红色群集是公共广播电台,蓝色群集是新闻/谈话电台。 这些类别是从Radio Locator派生的,与指纹识别过程无关。

令人兴奋的是,我们的指纹识别结果在很大程度上与外部识别类别的聚集方式相同。 另外值得注意的是几个棕色的节点,即大学广播电台。 即使降低了是否链接站点的阈值,它们也倾向于保持未链接状态,这表明大量的独特内容。

在这里玩可观察的笔记本!

结论

总体而言,音频指纹识别已被证明能够提高我们重复检测的准确性,并且自10月份以来,它已经在我们的基础架构中成功运行。 将来,我们希望着眼于商业检测(经常重复播放30秒的剪辑),也希望去除银团内容,以便对来自全国各地的口音进行培训/测试。

如果您对建立这样的整洁流程感兴趣,那么现在就是您的机会-我们正在招聘,希望能收到您的来信!

非常感谢Jordan Isler对音频指纹的初步调查,Madeleine Li孜孜不倦地收听音频,以及Brandon Roy在整个过程中坚定的调试和指导!

有关此博客文章的更深入的视频版本,请参阅我去年秋天在纽约市的DataEngConf上的演讲: