谷歌VAD静音检测py-webrtcvad使用详解

2023-11-13

一、前言

        不知道有没有人和我一样看的官方示例一脸蒙,什么采样率除以时间,看到就头大,还是英文头更大了

 好了废话结束,上翻译改编版

二、人话翻译版代码

如果你问我有些行为什么没有注释?

-

import collections
import contextlib
import sys
import wave
import os
import webrtcvad

#读取wav判断能否继续
def read_wave(path):
    #以二进制方式堆区音频数据
    with contextlib.closing(wave.open(path, 'rb')) as wf:
        #获取声道数,为1时继续执行
        num_channels = wf.getnchannels()
        assert num_channels == 1
        #采样字节长度,为2时继续执行
        sample_width = wf.getsampwidth()
        assert sample_width == 2
        #获取采样率,当采样率为8000,16000,32000时继续执行
        sample_rate = wf.getframerate()
        assert sample_rate in (8000, 16000, 32000)
        pcm_data = wf.readframes(wf.getnframes())
        #返回wav的二进制数据与采样率
        return pcm_data, sample_rate


def write_wave(path, audio, sample_rate):
    with contextlib.closing(wave.open(path, 'wb')) as wf:
        #设置声道
        wf.setnchannels(1)
        # 设置采样字节长度
        wf.setsampwidth(2)
        # 设置采样率
        wf.setframerate(sample_rate)
        # 写入数据
        wf.writeframes(audio)


class Frame(object):
    """Represents a "frame" of audio data."""

    def __init__(self, bytes, timestamp, duration):
        self.bytes = bytes
        self.timestamp = timestamp
        self.duration = duration


def frame_generator(frame_duration_ms, audio, sample_rate):
    #采样率*秒数*声道数=量化大小
    n = int(sample_rate * (frame_duration_ms / 1000.0) * 2)
    offset = 0
    timestamp = 0.0
    #量化大小对应的音频时间
    duration = (float(n) / sample_rate) / 2.0
    #如果offset起始量化大小加上量化大小小于音频 -->用来切分音频
    while offset + n < len(audio):
        #创建多个Frame类,用来存数据   audio[offset:offset + n]切出来的那一段数据,timestamp这段音频开始时间,duration这段音频的长度
        yield Frame(audio[offset:offset + n], timestamp, duration)
        timestamp += duration
        offset += n


def vad_collector(sample_rate, buffer_size, vad, frames):
    # 创建一个有两端的容器,数据溢出用来排除非人声
    ring_buffer = collections.deque(maxlen=buffer_size)

    triggered = False

    voiced_frames = []
    for frame in frames:
        # 把二进制数据和采样率交给vad
        is_speech = vad.is_speech(frame.bytes, sample_rate)
        #检测说话的开始
        if not triggered:
            # 在容器里添加一个对象(Frame类的实例,静音检测结果(True表示有人说))
            ring_buffer.append((frame, is_speech))
            #f = Frame() speech = is_speech 得到有人声音的Frame的个数
            num_voiced = len([f for f, speech in ring_buffer if speech])
            # 当说话段数量大于缓冲区的90%时认为人声开始,所以进入if时前10段有人声恰好在ring_buffer里
            if num_voiced > 0.9 * ring_buffer.maxlen:
                # 通知循环已经找到了音频开始位置
                triggered = True
                #输出当前片段的开始时间
                # 当有9条是人声时,那么最先放进去的一条就是起始位置
                sys.stdout.write('+(%s)' % (ring_buffer[0][0].timestamp,))
                # 把音频的二进制数据放到列表
                for f, s in ring_buffer:
                    voiced_frames.append(f)
                #清空缓存区
                ring_buffer.clear()
        # 检测说话的结束
        else:
            # 上面清空了缓存区,所以现在开始写入有人声的数据
            voiced_frames.append(frame)
            # 把人声的数据写到列表
            ring_buffer.append((frame, is_speech))
            # 获取有多少静音段被写到了ring_buffer
            num_unvoiced = len([f for f, speech in ring_buffer if not speech])
            # 当静音段数量大于90%时执行
            if num_unvoiced > 0.9 * ring_buffer.maxlen:
                # 此时ring_buffer里有10段静音,那么第一段就是人声的结束位置
                sys.stdout.write('-(%s)' % (frame.timestamp + frame.duration))
                # 通知函数找到结束
                triggered = False
                # 暂停当前函数,并返回数据
                yield b''.join([f.bytes for f in voiced_frames])
                # 因为下次调用函数会从yield后面的语句开始所以删除上一段音频数据
                ring_buffer.clear()
                voiced_frames = []
    #如果到音频结束还没有找到结束时,执行到这里,把音频结束当做人声结束, 这里frame自然就是最后一个
    if triggered:
        sys.stdout.write('-(%s)' % (frame.timestamp + frame.duration))
    sys.stdout.write('\n')
    #列表部为空返回所有数据
    if voiced_frames:
        yield b''.join([f.bytes for f in voiced_frames])


def main():
    path = r"./"
    files = os.listdir(path)
    files = [path + "\\" + f for f in files if f.endswith('.wav')]
    con = 1
    for i in range(len(files)):
        args = [3, files[i]]
        #二进制数据,采样率
        audio, sample_rate = read_wave(args[1])
        # 创建VAD实例,并设置模式
        vad = webrtcvad.Vad(int(args[0]))
        #切分数据并返回一堆用来存放数据的Rrame类的生成器
        frames = frame_generator(30, audio, sample_rate)
        frames = list(frames)
        #获取人声段的二进制数据 10决定缓冲区大小
        segments = vad_collector(sample_rate, 10, vad, frames)
        # 给列表加上一个索引(多条音频时使用,segments被)
        for j, segment in enumerate(segments):
            path = './data/' + 'chunk-%002d.wav' % (con,)
            print(' Writing %s' % (path,))
            write_wave(path, segment, sample_rate)
            con += 1


if __name__ == '__main__':
    main()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谷歌VAD静音检测py-webrtcvad使用详解 的相关文章

  • 多重处理:如何从子进程重定向标准输出?

    注意 我见过multiprocessing Process 的日志输出 https stackoverflow com questions 1501651 log output of multiprocessing process 不幸的是
  • 在 python 的 Visual Studio 工具中按下 ctrl+F5 后,控制台窗口立即关闭

    我已经安装了 Visual Studio 的 Python 工具 但在控制台窗口中看不到输出 就像我在 Visual Studio 中运行 C 控制台应用程序时按以下快捷键时看到的输出一样 F5 开始调试程序并关闭 C 和 Python 中
  • 使用Python的工业视觉相机[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 为什么方法无法访问类变量?

    我试图理解Python中的变量作用域 除了我不明白为什么类变量不能从其方法访问的部分之外 大多数事情对我来说都很清楚 在下面的例子中mydef1 无法访问a 但如果a可以在全局范围 类定义之外 声明 class MyClass1 a 25
  • 无法将 datetime.datetime 与 datetime.date 进行比较

    我有以下代码并收到上述错误 由于我是 python 新手 我无法理解这里的语法以及如何修复错误 if not start or date lt start start date 有一个datetime date 从日期时间转换为日期的方法
  • DataFrame 中的字符串,但 dtype 是对象

    为什么 Pandas 告诉我我有对象 尽管所选列中的每个项目都是一个字符串 即使在显式转换之后也是如此 这是我的数据框
  • Pytest:如何使用从夹具返回的列表来参数化测试?

    我想使用由固定装置动态创建的列表来参数化测试 如下所示 pytest fixture def my list returning fixture depends on other fixtures return a dynamically
  • 无法安装时间模块

    我试过了pip install time and sudo H pip install time 但我不断收到错误 找不到满足要求时间的版本 从 版本 未找到时间匹配的发行版 我正在 PyCharm 中工作 但真正没有意义的是我可以在 Py
  • 一起使用 Argparse 和 Json

    我是 Python 初学者 我想知道 Argparse 和 JSON 是否可以一起使用 说 我有变量p q r 我可以将它们添加到 argparse 中 parser add argument p param1 help x variabl
  • 熊猫记忆

    我有冗长的计算 我重复了很多次 因此 我想使用记忆 诸如jug http packages python org Jug and joblib http packages python org joblib memory html 与Pan
  • 如何检查包含 NaN 的列表 [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 在我的 for 循环中 我的代码生成一个如下所示的列表 list 0 0 0 0 sum 0 0 0 0 该循环生成所有其他数字向量 但它也
  • 如何将同步函数包装在异步协程中?

    我在用着aiohttp https github com aio libs aiohttp构建一个 API 服务器 将 TCP 请求发送到单独的服务器 发送 TCP 请求的模块是同步的 对于我来说是一个黑匣子 所以我的问题是这些请求阻塞了整
  • 如何使用注释和聚合在 Django 的 ORM 中执行此 GROUP BY 查询

    我真的不知道如何翻译GROUP BY and HAVING到姜戈的QuerySet annotate and QuerySet aggregate 我正在尝试将这个 SQL 查询转换为 ORM 语言 SELECT EXTRACT year
  • 如何将reportlab与Google应用程序引擎一起使用

    我无法在谷歌应用程序引擎下正确导入reportlab 根据以下guide http blog notdot net 2010 04 Generating PDFs on App Engine Python and introducing M
  • 在 Python 中,如何获取特定文件中定义的类列表?

    如果一个文件myfile py包含 class A object Some implementation class B object Some implementation 我如何定义一个方法 以便在给定的情况下myfile py 它返回
  • django如何将字符串转换为模块?

    我试图了解 django 的另一个神奇之处 它可以将字符串转换为模块 In settings py INSTALLED APPS声明如下 INSTALLED APPS django contrib auth django contrib c
  • DRF:以编程方式从 TextChoices 字段获取默认选择

    我们的网站是 Vue 前端 DRF 后端 在一个serializer validate 方法 我需要以编程方式确定哪个选项TextChoices类已被指定为模型字段的默认值 TextChoices 类 缩写示例 class PaymentM
  • Python“self”关键字[重复]

    这个问题在这里已经有答案了 我是 Python 新手 通常使用 C 最近几天开始使用它 在类中 是否需要在对该类的数据成员和方法的任何调用前添加前缀 因此 如果我在该类中调用方法或从该类获取值 我需要使用self method or sel
  • 字母尺度和随机文本上的马尔可夫链

    我想使用 txt 文件中的一本书中的字母频率生成随机文本 以便每个新字符 string lowercase 取决于前一个 如何使用马尔可夫链来做到这一点 或者使用每个字母都有条件频率的 27 个数组更简单 我想使用来自的字母频率生成随机文本
  • 使用Python重命名目录中的多个文件

    我正在尝试使用以下 Python 脚本重命名目录中的多个文件 import os path Users myName Desktop directory files os listdir path i 1 for file in files

随机推荐

  • 基于控制的角度无人机集群——目标追踪

    无人机集群 目标追踪 前言 一 轨迹预测 二 单目标追踪 三 多目标追踪 前言 关于目标追踪问题 有一些研究是从视觉的角度展开 而我研究的是基于控制的角度 关于多无人机集群的一些知识点 已经在上一篇文章有了简单介绍 这次我想着重介绍一下 目
  • 4.抽样分布的概念与Python实现抽样

    1 总体与样本 在实际中 总体的分布一般是未知的 或只知道它具有某种形式而其中包含着未知参数 这时 常用的办法就是根据样本来推断总体 总体 个体 样本 总体 通常把研究对象的全体称为总体 一个总体对应于一个随机变量X 个体 把组成总体的每个
  • CTFshow 信息收集 web 6 7 8 9 10

    目录 第六关 提示 flag 第七关 提示 知识点 flag 第八关 提示 知识点 flag 第九关 提示 知识点 flag 第十关 提示 flag 第六关 提示 解压源码到当前目录 测试正常 收工 这道题考的是备份文件www zip 根据
  • 解决mysql占用IO过高

    created 2023 01 30T10 14 00 UTC 08 00 tags source https www bbsmax com A Ae5RyA0AJQ author 解决mysql占用IO过高 Excerpt 1 日志产生的
  • 西门子HMI设备与V20变频器如何实现通讯?

    通常情况下 要实现HMI设备与V20变频器的通讯 需要一个支持USS通讯或MODBUS通讯的PLC 比如S7 200系列PLC 其通讯电缆连接如图1所示 PLC的一个通讯端口与触摸屏连接 可以采用PPI协议通讯 PLC的另一个通讯端口与V2
  • C语言自定义类型-结构体

    一 结构体声明 C语言中为我们准备了许多现成的数据类型例如 int short float double char long long long 等等 但是我们描述一些复杂的事物 光靠上述的数据类型是描述不清的 例如 我们描述一个大学生 可
  • 安卓Android_手机安装burp的https_CA证书

    安卓Android 手机安装burp的https CA证书 文章目录 安卓Android 手机安装burp的https CA证书 1 打卡电脑wif热点 手机连上电脑的热点 2 burp点击 Proxy settings 3 点击add 新
  • java 数组中插入元素_Java数组添加元素

    java 数组中插入元素 How to add elements to an array in java We know that java array size is fixed so we can t add elements to a
  • jvm虚拟机所有垃圾回收器详细介绍

    jvm虚拟机所有垃圾回收器详细介绍 文章目录 jvm虚拟机所有垃圾回收器详细介绍 垃圾回收器概述 1 Serial回收器 串行回收 总结 2 ParNew回收器 并行回收 3 Parallel Scavenge回收器 吞吐量优先 4 CMS
  • 论文解读 《Enhancing Underwater Imagery using Generative Adversarial Networks》ICRA2018

    项目 http irvlab cs umn edu enhancing underwater imagery using gans 论文 https arxiv org pdf 1801 04011 pdf 代码 https github
  • 算法精解_C语言 链表_单链表(接口定义+类型实现)

    链表可以说是一种最为基础的数据结构 链表由一组元素以一种特定的顺序组合或链接而成 在维护数据的集合时很有用 这一点同我们常用的数组很相似 然而 链表在很多情况下比数组更有优势 特别是在执行插入和删除操作时链表拥有更高的效率 链表需要动态的开
  • 组件化依赖管理办法

    theme channing cyan 在组件化过程中 面临着非常多的复用 切换等场景 对于组件化中的dsl文件 也可以尝试将其组件出来 更好的复用 更好的管理 一 利用buildSrc buildscript 对dsl 文件进行组件化 1
  • org.postgresql.util.PSQLException: 错误: 关系 “courseinformation“ 不存在

    问题描述 在java项目中连接PSQL数据库 对courseinformation表进行操作时 运行报错 org postgresql util PSQLException 错误 关系 courseinformation 不存在 已知解决方
  • BUUCTF系列 // [极客大挑战 2019] LoveSQL

    前言 本题知识点 SQL注入 WP 这题居然是个连续剧 首先尝试使用上一题的解法绕过看看 上一题 WP 的 传送门 结果如下 注意到密码有些奇怪 尝试着用 MD5 解码失败 也没啥思路 最后事实证明确实也用不到这玩意 故回到 SQL 注入上
  • 人工智能数学基础8:两个重要极限及夹逼定理

    点此跳转到老猿Python博文目录 一 极限公式1 二 极限公式2 e为常数2 71828 变体 使用案例 三 夹逼定理 夹逼定理英文原名Squeeze Theorem 也称两边夹定理 夹逼准则 夹挤定理 挟挤定理 三明治定理 是判定极限存
  • JAVA程序设计:最短回文串(LeetCode:214)

    给定一个字符串 s 你可以通过在字符串前面添加字符将其转换为回文串 找到并返回可以用这种方式转换的最短回文串 示例 1 输入 aacecaaa 输出 aaacecaaa 示例 2 输入 abcd 输出 dcbabcd 思路 这题O N 2
  • python-selenium-运行js代码--下拉操作

    使用python selenium运行js代码完成下拉操作 在某些情况 当我们下拉到浏览器 浏览器才会给我们加载数据 所有我们需要js带代码 driver execute script 写入你要执行的js代码 下拉的js代码 documen
  • 什么是CRUD( What is CRUD)?

    在很多技术性的文章 特别是有关数据库类的文章中 经常会看到一个缩写 CRUD 那什么是CRUD呢 CRUD其实是数据库基本操作中的Create 创建 ReadRetrieve 读取 Update 更新 Delete 删除 而这里的Creat
  • pycharm中pygame模块的安装与用法

    一 pygame的安装 本文章主要展示pycharm中的pygame模块的安装 打开pycharm 在左上角点file 找到settings 如图 进入后 找到Project untitled下的Project interperter 右边
  • 谷歌VAD静音检测py-webrtcvad使用详解

    一 前言 不知道有没有人和我一样看的官方示例一脸蒙 什么采样率除以时间 看到就头大 还是英文头更大了 好了废话结束 上翻译改编版 二 人话翻译版代码 如果你问我有些行为什么没有注释 import collections import con