| from typing import Tuple |
| import wave |
| import os |
|
|
| import torchaudio |
| from vad import EnergyVAD |
| TARGET_SAMPLING_RATE = 16000 |
|
|
| def create_frames(data: bytes, frame_duration: int) -> Tuple[bytes]: |
| frame_size = int(TARGET_SAMPLING_RATE * (frame_duration / 1000)) |
| return (data[i:i + frame_size] for i in range(0, len(data), frame_size)), frame_size |
|
|
| def detect_activity(energies: list): |
| if sum(energies) < len(energies) / 12: |
| return False |
| count = 0 |
| for energy in energies: |
| if energy == 1: |
| count += 1 |
| if count == 12: |
| return True |
| else: |
| count = 0 |
| return False |
|
|
| class Client: |
| def __init__(self, sid, client_id, call_id=None): |
| self.sid = sid |
| self.client_id = client_id |
| self.call_id = call_id |
| self.buffer = bytearray() |
| self.output_path = self.sid + "_output_audio.wav" |
| self.target_language = None |
| self.original_sr = None |
| self.vad = EnergyVAD( |
| sample_rate=TARGET_SAMPLING_RATE, |
| frame_length=25, |
| frame_shift=20, |
| energy_threshold=0.05, |
| pre_emphasis=0.95, |
| ) |
|
|
| def add_bytes(self, new_bytes): |
| self.buffer += new_bytes |
|
|
| def resample_and_write_to_file(self): |
| print("Audio being written to file....\n") |
| with wave.open(self.sid + "_OG.wav", "wb") as wf: |
| wf.setnchannels(1) |
| wf.setsampwidth(2) |
| wf.setframerate(self.original_sr) |
| wf.setnframes(0) |
| wf.setcomptype("NONE", "not compressed") |
| wf.writeframes(self.buffer) |
| waveform, sample_rate = torchaudio.load(self.sid + "_OG.wav") |
| resampler = torchaudio.transforms.Resample(sample_rate, TARGET_SAMPLING_RATE, dtype=waveform.dtype) |
| resampled_waveform = resampler(waveform) |
| |
| vad_waveform = self.vad(resampled_waveform) |
| |
| self.buffer = bytearray() |
| return detect_activity(vad_waveform), resampled_waveform |
| |
| def get_length(self): |
| return len(self.buffer) |
| |
| def __del__(self): |
| if len(self.buffer) > 0: |
| print(f"🚨 [ClientAudioBuffer] Buffer not empty for {self.sid} ({len(self.buffer)} bytes)!") |
| if os.path.exists(self.output_path): |
| os.remove(self.output_path) |
| if os.path.exists(self.sid + "_OG.wav"): |
| os.remove(self.sid + "_OG.wav") |
|
|
|
|