python检测音频中的静音
#-*- coding: utf-8 -*-
import os
import wave
from time import sleep
import numpy as np SUCCESS = 0
FAIL = 1 # 需要添加录音互斥功能能,某些功能开启的时候录音暂时关闭
def ZCR(curFrame):
# 过零率
tmp1 = curFrame[:-1]
tmp2 = curFrame[1:]
sings = (tmp1 * tmp2 <= 0)
diffs = (tmp1 - tmp2) > 0.02
zcr = np.sum(sings * diffs)
return zcr def STE(curFrame):
# 短时能量
amp = np.sum(np.abs(curFrame))
return amp class Vad(object):
def __init__(self):
# 初始短时能量高门限
self.amp1 = 140
# 初始短时能量低门限
self.amp2 = 120
# 初始短时过零率高门限
self.zcr1 = 10
# 初始短时过零率低门限
self.zcr2 = 5
# 允许最大静音长度
self.maxsilence = 100
# 语音的最短长度
self.minlen = 40
# 偏移值
self.offsets = 40
self.offsete = 40
# 能量最大值
self.max_en = 20000
# 初始状态为静音
self.status = 0
self.count = 0
self.silence = 0
self.frame_len = 256
self.frame_inc = 128
self.cur_status = 0
self.frames = []
# 数据开始偏移
self.frames_start = []
self.frames_start_num = 0
# 数据结束偏移
self.frames_end = []
self.frames_end_num = 0
# 缓存数据
self.cache_frames = []
self.cache = ""
# 最大缓存长度
self.cache_frames_num = 0
self.end_flag = False
self.wait_flag = False
self.on = True
self.callback = None
self.callback_res = []
self.callback_kwargs = {} def clean(self):
self.frames = []
# 数据开始偏移
self.frames_start = []
self.frames_start_num = 0
# 数据结束偏移
self.frames_end = []
self.frames_end_num = 0
# 缓存数据
self.cache_frames = []
# 最大缓存长度
self.cache_frames_num = 0
self.end_flag = False
self.wait_flag = False def go(self):
self.wait_flag = False def wait(self):
self.wait_flag = True def stop(self):
self.on = False def add(self, frame, wait=True):
if wait:
print 'wait'
frame = self.cache + frame while len(frame) > self.frame_len:
frame_block = frame[:self.frame_len]
self.cache_frames.append(frame_block)
frame = frame[self.frame_len:]
if wait:
self.cache = frame
else:
self.cache = ""
self.cache_frames.append(-1) def run(self,hasNum):
print "开始执行音频端点检测"
step = self.frame_len - self.frame_inc
num = 0
while 1:
# 开始端点
# 获得音频文件数字信号
if self.wait_flag:
sleep(1)
continue
if len(self.cache_frames) < 2:
sleep(0.05)
continue if self.cache_frames[1] == -1:
print '----------------没有声音--------------'
break
# 从缓存中读取音频数据
record_stream = "".join(self.cache_frames[:2])
wave_data = np.fromstring(record_stream, dtype=np.int16)
wave_data = wave_data * 1.0 / self.max_en
data = wave_data[np.arange(0, self.frame_len)]
speech_data = self.cache_frames.pop(0)
# 获得音频过零率
zcr = ZCR(data)
# 获得音频的短时能量, 平方放大
amp = STE(data) ** 2
# 返回当前音频数据状态
res = self.speech_status(amp, zcr) if res == 2:
hasNum += 1 if hasNum > 10:
print '+++++++++++++++++++++++++有声音++++++++++++++++++++++++'
break
num = num + 1
# 一段一段进行检测
self.frames_start.append(speech_data)
self.frames_start_num += 1
if self.frames_start_num == self.offsets:
# 开始音频开始的缓存部分
self.frames_start.pop(0)
self.frames_start_num -= 1
if self.end_flag:
# 当音频结束后进行后部缓存
self.frames_end_num += 1
# 下一段语音开始,或达到缓存阀值
if res == 2 or self.frames_end_num == self.offsete:
speech_stream = b"".join(self.frames + self.frames_end)
self.callback_res.append(self.callback(speech_stream, **self.callback_kwargs)) # 数据环境初始化
# self.clean()
self.end_flag = False self.frames = []
self.frames_end_num = 0
self.frames_end = [] self.frames_end.append(speech_data)
if res == 2:
if self.cur_status in [0, 1]:
# 添加开始偏移数据到数据缓存
self.frames.append(b"".join(self.frames_start))
# 添加当前的语音数据
self.frames.append(speech_data)
if res == 3:
print '检测音频结束'
self.frames.append(speech_data)
# 开启音频结束标志
self.end_flag = True self.cur_status = res
# return self.callback_res def speech_status(self, amp, zcr):
status = 0
# 0= 静音, 1= 可能开始, 2=确定进入语音段
if self.cur_status in [0, 1]:
# 确定进入语音段
if amp > self.amp1:
status = 2
self.silence = 0
self.count += 1
# 可能处于语音段
elif amp > self.amp2 or zcr > self.zcr2:
status = 1
self.count += 1
# 静音状态
else:
status = 0
self.count = 0
self.count = 0
# 2 = 语音段
elif self.cur_status == 2:
# 保持在语音段
if amp > self.amp2 or zcr > self.zcr2:
self.count += 1
status = 2
# 语音将结束
else:
# 静音还不够长,尚未结束
self.silence += 1
if self.silence < self.maxsilence:
self.count += 1
status = 2
# 语音长度太短认为是噪声
elif self.count < self.minlen:
status = 0
self.silence = 0
self.count = 0
# 语音结束
else:
status = 3
self.silence = 0
self.count = 0
return status def read_file_data(filename):
"""
输入:需要读取的文件名
返回:(声道,量化位数,采样率,数据)
"""
read_file = wave.open(filename, "r")
params = read_file.getparams()
nchannels, sampwidth, framerate, nframes = params[:4]
data = read_file.readframes(nframes)
return nchannels, sampwidth, framerate, data class FileParser(Vad):
def __init__(self):
self.block_size = 256
Vad.__init__(self)
def read_file(self, filename):
if not os.path.isfile(filename):
print "文件%s不存在" % filename
return FAIL
datas = read_file_data(filename)[-1]
self.add(datas, False) if __name__ == "__main__":
stream_test = FileParser() filename = 'test1566606924822.wav'
result = stream_test.read_file(filename)
if result != FAIL:
stream_test.run(0)
转载自网络,版权归原作者所有
python检测音频中的静音的更多相关文章
- 使用python检测一个设备是否ping的通
使用python检测一个设备是否ping的通 一,subprocess以及常用的封装函数 运行python的时候,我们都是在创建并运行一个进程.像Linux进程那样,一个进程可以fork一个子进程,并 ...
- python检测404页面
某些网站为了实现友好的用户交互,提供了一种自定义的错误页面,而不是显示一个大大的404 ,比如CSDN上的404提示页面如下: 这样虽然提高了用户体验,但是在编写对应POC进行检测的时候如果只根据返回 ...
- Python基础(中)
前言 print(" _ooOoo_ ") print(" o8888888o ") print(" 88 . 88 ") print(&q ...
- python检测服务器是否ping通
好想在2014结束前再赶出个10篇博文来,~(>_<)~,不写博客真不是一个好兆头,至少说明对学习的欲望和对知识的研究都不是那么积极了,如果说这1天的时间我能赶出几篇精致的博文,你们信不信 ...
- python检测变量名
python检测变量名 变量在编程中的用途非常广,在python中,变量的名称只能以字母或者下划线“_”开头,变量名只能由字母.数字.下划线组成. 编写python,使得其实现以下功能: 1.输入一个 ...
- Python实现MATLAB中的 bwlabel函数
最近做验证码识别,原本用MATLAB已经实现的整个识别模型,不过代码要部署在Linux服务器上还是需要用另外的语言实现,于是决定用Python + OpenCV来实现. bwlabel函数的作用是检测 ...
- 使用Python将Excel中的数据导入到MySQL
使用Python将Excel中的数据导入到MySQL 工具 Python 2.7 xlrd MySQLdb 安装 Python 对于不同的系统安装方式不同,Windows平台有exe安装包,Ubunt ...
- imagesLoaded – 检测网页中的图片是否加载
imagesLoaded 是一个用于来检测网页中的图片是否载入完成的 JavaScript 工具库.支持回调的获取图片加载的进度,还可以绑定自定义事件.可以结合 jQuery.RequireJS 使用 ...
- javascript,检测对象中是否存在某个属性
检测对象中属性的存在与否可以通过几种方法来判断. 1.使用in关键字. 该方法可以判断对象的自有属性和继承来的属性是否存在. var o={x:1}; "x" in o; //tr ...
随机推荐
- 在idea中如何将一个项目打成war包
s会用clean+package两个组合命令.来进行打包,我的war直接打在了target下面.然后,随时可以找到.war文件
- 靠边的列表如果没有设置margin-left:20px,那么是看不到列表序号的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- sql server 数据类型转换
--这是显示转换类型,将字符串转成整形SELECT CAST('1' AS int),CONVERT(int,'1')--SqlServer也会隐式转换,如:用字符串乘以一个整形,--整形优先级要大, ...
- 14 | count(*)这么慢,我该怎么办?
在开发系统的时候,你可能经常需要计算一个表的行数,比如一个交易系统的所有变更记录总数.这时候你可能会想,一条select count(*) from t 语句不就解决了吗? 但是,你会发现随着系统中记 ...
- 洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom 题解
每日一题 day11 打卡 Analysis 好久没大Tarjan了,练习练习模板. 只要在Tarjan后扫一遍si数组看是否大于1就好了. #include<iostream> #inc ...
- 洛谷 P2119 魔法阵 题解
Analysis 这道题也是考试题,我也依然打了个n三次方暴力.正解是先枚举差,再枚举c和d,a和b用乘法原理优化,这样就能大大减少时间. #include<iostream> #incl ...
- Wireshark抓取本地回环接口数据包 RawCap.exe
Wireshark提供了winpcap可以抓取远程网卡数据包...但我尝试了不成功.后来发现RawCap.exe不仅可以抓取回环接口数据包,远程跑了拿到pcap文件再打开用起来比winpcap更方便最 ...
- LibreOJ #115. 无源汇有上下界可行流
二次联通门 : LibreOJ #115. 无源汇有上下界可行流 /* LibreOJ #115. 无源汇有上下界可行流 板子题 我也就会写写板子题了.. */ #include <cstdio ...
- NetworkX系列教程(10)-算法之二:最小/大生成树问题
小书匠 Graph 图论 重头戏部分来了,写到这里我感觉得仔细认真点了,可能在NetworkX中,实现某些算法就一句话的事,但是这个算法是做什么的,用在什么地方,原理是怎么样的,不清除,所以,我决定 ...
- qml 绘制高精地图之怀疑人生的加载速度
绘制高精地图时需要gps的经纬度坐标,之前的实现方式是QGeocoordinate类的经纬度变量通过json的方式在qml中使用. 以画线为例,使用方式是这样哒. for(var i in vehic ...