mirror of
https://github.com/xinnan-tech/xiaozhi-esp32-server.git
synced 2026-07-22 07:03:53 +08:00
update:恢复vad判断
This commit is contained in:
@@ -454,7 +454,7 @@ VAD:
|
||||
threshold: 0.5
|
||||
threshold_low: 0.3
|
||||
model_dir: models/snakers4_silero-vad
|
||||
min_silence_duration_ms: 200 # 如果说话停顿比较长,可以把这个值设置大一些,实际延迟为:min_silence_duration_ms // 32 * 32ms
|
||||
min_silence_duration_ms: 200 # 如果说话停顿比较长,可以把这个值设置大一些
|
||||
|
||||
LLM:
|
||||
# 所有openai类型均可以修改超参,以AliLLM为例
|
||||
|
||||
@@ -115,10 +115,10 @@ class ConnectionHandler:
|
||||
# vad相关变量
|
||||
self.client_audio_buffer = bytearray()
|
||||
self.client_have_voice = False
|
||||
self.client_voice_window = deque(maxlen=5)
|
||||
self.last_activity_time = 0.0 # 统一的活动时间戳(毫秒)
|
||||
self.client_voice_stop = False
|
||||
self.last_is_voice = False
|
||||
self.continuous_false_count = 0
|
||||
|
||||
# asr相关变量
|
||||
# 因为实际部署时可能会用到公共的本地ASR,不能把变量暴露给公共ASR
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import time
|
||||
import torch
|
||||
import numpy as np
|
||||
import torch
|
||||
import opuslib_next
|
||||
from config.logger import setup_logging
|
||||
from core.providers.vad.base import VADProviderBase
|
||||
@@ -26,12 +26,15 @@ class VADProvider(VADProviderBase):
|
||||
threshold_low = config.get("threshold_low", "0.2")
|
||||
min_silence_duration_ms = config.get("min_silence_duration_ms", "1000")
|
||||
|
||||
# 双阈值判断参数
|
||||
self.vad_threshold = float(threshold) if threshold else 0.5
|
||||
self.vad_threshold_low = float(threshold_low) if threshold_low else 0.2
|
||||
|
||||
# 静默阈值,连续多少帧低于最低值才判断为静音
|
||||
self.stop_false_count = int(min_silence_duration_ms) // 32 if min_silence_duration_ms else 31
|
||||
self.silence_threshold_ms = (
|
||||
int(min_silence_duration_ms) if min_silence_duration_ms else 1000
|
||||
)
|
||||
|
||||
# 至少要多少帧才算有语音
|
||||
self.frame_window_threshold = 3
|
||||
|
||||
def is_vad(self, conn, opus_packet):
|
||||
try:
|
||||
@@ -56,24 +59,26 @@ class VADProvider(VADProviderBase):
|
||||
|
||||
# 双阈值判断
|
||||
if speech_prob >= self.vad_threshold:
|
||||
client_have_voice = True
|
||||
is_voice = True
|
||||
elif speech_prob <= self.vad_threshold_low:
|
||||
client_have_voice = False
|
||||
is_voice = False
|
||||
else:
|
||||
client_have_voice = conn.last_is_voice
|
||||
|
||||
if not client_have_voice:
|
||||
conn.continuous_false_count += 1
|
||||
else:
|
||||
conn.continuous_false_count = 0
|
||||
is_voice = conn.last_is_voice
|
||||
|
||||
# 声音没低于最低值则延续前一个状态,判断为有声音
|
||||
conn.last_is_voice = client_have_voice
|
||||
conn.last_is_voice = is_voice
|
||||
|
||||
# 如果之前有声音,且连续为静音帧,达到静默阈值要求帧数,则认为已经说完一句话
|
||||
if conn.client_have_voice and conn.continuous_false_count >= self.stop_false_count:
|
||||
conn.client_voice_stop = True
|
||||
# 更新滑动窗口
|
||||
conn.client_voice_window.append(is_voice)
|
||||
client_have_voice = (
|
||||
conn.client_voice_window.count(True) >= self.frame_window_threshold
|
||||
)
|
||||
|
||||
# 如果之前有声音,但本次没有声音,且与上次有声音的时间差已经超过了静默阈值,则认为已经说完一句话
|
||||
if conn.client_have_voice and not client_have_voice:
|
||||
stop_duration = time.time() * 1000 - conn.last_activity_time
|
||||
if stop_duration >= self.silence_threshold_ms:
|
||||
conn.client_voice_stop = True
|
||||
if client_have_voice:
|
||||
conn.client_have_voice = True
|
||||
conn.last_activity_time = time.time() * 1000
|
||||
|
||||
Reference in New Issue
Block a user