omni / src /serve /realtime.py
chenbhao's picture
Add omni_o_call.py: real-time voice call server for omni-o checkpoint
f268594
Raw
History Blame Contribute Delete
2.64 kB
import numpy as np
import torch
class SileroVAD:
def __init__(self, path=None):
from silero_vad import load_silero_vad
self.vad = load_silero_vad(onnx=True)
def reset(self):
self.vad.reset_states()
def __call__(self, chunk, sr=16000):
if chunk.shape[-1] not in (256, 512):
return 0.0
t = torch.from_numpy(chunk.reshape(1, -1).astype(np.float32))
return float(self.vad(t, sr))
class RealtimeSession:
def __init__(self, vad_path, sr=16000, threshold=0.5, min_speech_ms=128, min_silence_ms=800):
self.vad, self.sr, self.threshold = SileroVAD(vad_path), sr, threshold
self.min_speech, self.min_silence = int(sr * min_speech_ms / 1000), int(sr * min_silence_ms / 1000)
self.reset()
def reset(self):
self.vad.reset()
self.buffer, self.ring, self.speaking, self.generating, self.interrupt = [], [], False, False, False
self.speech_samples = self.silence_samples = self.tail_silence = 0
def push_chunk(self, chunk, W=512):
for i in range(0, max(len(chunk), 1), W):
w = chunk[i:i + W]
if len(w) < W:
w = np.pad(w, (0, W - len(w)))
prob = self.vad(w, self.sr)
if prob > self.threshold:
self.silence_samples = self.tail_silence = 0
self.speech_samples += len(w)
self.buffer.append(w)
if self.speech_samples >= self.min_speech and not self.speaking:
self.speaking = True
self.buffer = self.ring + self.buffer
self.ring = []
if self.generating and self.speaking:
self.interrupt = True
return 'interrupt'
elif self.speaking:
self.silence_samples += len(w)
self.tail_silence += 1
self.buffer.append(w)
if self.silence_samples >= self.min_silence:
if self.tail_silence > 1:
del self.buffer[-(self.tail_silence - 1):]
self.speaking, self.speech_samples, self.silence_samples, self.tail_silence = False, 0, 0, 0
return 'speech_end'
else:
if self.speech_samples > 0:
self.buffer.clear()
self.speech_samples = 0
self.ring = [w]
return 'listening'
def get_audio(self):
audio = np.concatenate(self.buffer) if self.buffer else np.array([], dtype=np.float32)
self.buffer.clear()
return audio