使用VAD实现语音检测时调用vad.is_speech传帧报TypeError及帧格式疑问
webrtcvad调用is_speech方法报TypeError问题排查
问题描述
尝试使用VAD(语音活动检测器)实现语音检测,已可正常读取音频,但将音频帧传入VAD处理时出现报错,怀疑报错和传入的帧为字节格式有关,想确认vad.is_speech(frame, sample_rate)要求传入的frame是否为字节类型。
相关代码
frame_duration_ms=10 duration_in_ms = (frame_duration_ms / 1000) #duration in 10ms frame_size = int(sample_rate * duration_in_ms) #frame size of 160 frame_bytes = frame_size * 2 def frame_generator(buffer, frame_bytes): # repeatedly store 320 length array to the frame_stored when the frame_bytes is less than the size of the buffer while offset+frame_bytes < len(buffer): frame_stored = buffer[offset : offset+frame_bytes] offset = offset + frame_bytes return frame_stored num_padding_frames = int(padding_duration_ms / frame_duration_ms) # use deque for the sliding window ring_buffer = deque(maxlen=num_padding_frames) # we have two states TRIGGERED and NOTTRIGGERED state triggered = True #NOTTRIGGERED state frames = frame_generator(buffer, frame_bytes) speech_frame = [] for frame in frames: is_speech = vad.is_speech(frame, sample_rate)
报错信息
TypeError Traceback (most recent call last)
in
16 speech_frame = []
17 for frame in frames:
---> 18 is_speech = vad.is_speech(frame, sample_rate)
19 #print(frames)C:\Program Files\Python38\lib\site-packages\webrtcvad.py in is_speech(self, buf, sample_rate, length)
20
21 def is_speech(self, buf, sample_rate, length=None):
---> 22 length = length or int(len(buf) / 2)
23 if length * 2 > len(buf):
24 raise IndexError(TypeError: object of type 'int' has no len()
问题原因与修复方案
- 首先明确参数要求:
vad.is_speech()的第一个入参必须是16bit单声道PCM编码的bytes类型音频帧,方法内部依赖对传入参数求长度计算采样点个数,传入int、数值列表、numpy数组等非bytes类型都会触发长度计算失败的错误。 - 报错的直接原因不是字节格式问题,是
frame_generator的实现逻辑存在两个明显错误:- 函数内未初始化
offset变量,切片操作没有合法的起始位置 - 循环块内使用
return frame_stored直接返回整段长字节内容,没有将函数定义为可逐帧迭代的生成器;后续用for frame in frames遍历这个长bytes值时,会逐字节取出单个0-255范围的int值传给is_speech方法,方法内部尝试对int类型求长度时就会触发报错。
- 函数内未初始化
- 具体修复操作:
- 在
frame_generator函数开头添加offset = 0的初始化语句 - 将循环内的
return frame_stored改为yield frame_stored,让函数成为可逐帧产出独立bytes切片的生成器,遍历返回的才是符合类型要求的音频帧 - 额外校验前置条件:webrtcvad仅支持8kHz/16kHz/32kHz/48kHz采样率的单声道音频,输入帧时长仅支持10ms/20ms/30ms,对应16kHz采样率下的帧字节长度需为320/640/960,不符合长度要求的字节流会触发其他类型的报错
- 如果读取到的音频buffer是numpy数组格式的采样点,需要先将其转换为16bit小端序的bytes类型再做切片,不能直接将数组切片传入方法
- 在
内容的提问来源于stack exchange,提问作者dtovia
相关产品推荐
相关产品推荐

