Make this code more faster
import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

import sounddevice as sd
import numpy as np
import queue
import threading
import time
import webrtcvad
from faster_whisper import WhisperModel
import sys

# Parameters
sample_rate = 16000  # faster-whisper expects audio at 16000 Hz
frame_duration = 30  # Frame size in ms for VAD
num_channels = 1     # Mono audio
max_pause_duration = 0.8  # Max duration of silence (in seconds) to consider as a pause

# Initialize faster-whisper model
print("Loading faster-whisper model...")
model_size = "large-v3"
# Choose device: "cpu" or "cuda" (if you have a compatible GPU)
device = "cuda"
# Choose compute type: "int8", "int8_float16", "float16", or "float32"
compute_type = "int8" if device == "cpu" else "float16"
whisper_model = WhisperModel(model_size, device=device, compute_type=compute_type)

# Initialize VAD
vad = webrtcvad.Vad()
vad.set_mode(1)  # Aggressiveness mode (0-3). Higher values are more aggressive.

# Audio queue for communication between callback and processing thread
audio_queue = queue.Queue()
# Flag to stop the processing thread
stop_flag = threading.Event()

def audio_callback(indata, frames, time_info, status):
    """Callback function called by sounddevice for each audio block."""
    if status:
        print(f"Recording error: {status}", file=sys.stderr)
    # Store a copy of the audio data in the queue
    audio_queue.put(indata.copy())

def process_audio():
    """Thread function to process audio blocks from the queue."""
    audio_data = bytearray()
    last_voice_time = time.time()
    speech_active = False

    while not stop_flag.is_set():
        try:
            # Wait for an audio block from the queue
            indata = audio_queue.get(timeout=0.1)
        except queue.Empty:
            indata = None

        if indata is not None:
            # Convert audio block to 16-bit PCM
            pcm_data = (indata * 32768).astype(np.int16)
            pcm_bytes = pcm_data.tobytes()

            # Split audio into frames for VAD
            frame_size = int(sample_rate * frame_duration / 1000) * 2  # 2 bytes per sample (16-bit audio)
            frames = [pcm_bytes[i:i + frame_size] for i in range(0, len(pcm_bytes), frame_size)]

            for frame in frames:
                if len(frame) < frame_size:
                    # Ignore incomplete frames
                    continue
                is_speech = vad.is_speech(frame, sample_rate)
                if is_speech:
                    audio_data.extend(frame)
                    last_voice_time = time.time()
                    speech_active = True
                else:
                    if speech_active and (time.time() - last_voice_time > max_pause_duration):
                        # Detected pause in speech
                        # Convert accumulated audio to numpy array
                        audio_np = np.frombuffer(audio_data, np.int16).astype(np.float32) / 32768.0
                        if len(audio_np) == 0:
                            # No audio data to process
                            audio_data = bytearray()
                            speech_active = False
                            continue

                        print("Transcribing...")
                        # Transcribe with faster-whisper
                        segments, info = whisper_model.transcribe(audio_np, beam_size=1, language='en')

                        # Collect the transcribed text
                        transcribed_text = ''.join([segment.text for segment in segments]).strip()

                        if transcribed_text:
                            print(f"You said: {transcribed_text}\n")
                        # Reset for next utterance
                        audio_data = bytearray()
                        speech_active = False
        else:
            # No data received; check for silence after speech
            if speech_active and (time.time() - last_voice_time > max_pause_duration):
                # Convert accumulated audio to numpy array
                audio_np = np.frombuffer(audio_data, np.int16).astype(np.float32) / 32768.0
                if len(audio_np) == 0:
                    # No audio data to process
                    audio_data = bytearray()
                    speech_active = False
                    continue

                print("Transcribing...")
                segments, info = whisper_model.transcribe(audio_np, beam_size=1, language='en')

                transcribed_text = ''.join([segment.text for segment in segments]).strip()

                if transcribed_text:
                    print(f"You said: {transcribed_text}\n")
                 # Reset for next utterance
                audio_data = bytearray()
                speech_active = False

    # Process any remaining audio data when stopping
    if audio_data:
        audio_np = np.frombuffer(audio_data, np.int16).astype(np.float32) / 32768.0
        if len(audio_np) > 0:
            print("Final transcribing...")
            segments, info = whisper_model.transcribe(audio_np, beam_size=1, language='en')
            transcribed_text = ''.join([segment.text for segment in segments]).strip()
            if transcribed_text:
                print(f"You said: {transcribed_text}\n")

def main():
    try:
        # Start audio stream
        with sd.InputStream(callback=audio_callback,
                            channels=num_channels,
                            samplerate=sample_rate,
                            blocksize=int(sample_rate * frame_duration / 1000),
                            dtype='float32'):
            print("Listening... Press Ctrl+C to stop.")
            # Start audio processing thread
            threading.Thread(target=process_audio, daemon=True).start()
            # Keep the main thread alive
            while True:
                time.sleep(0.1)
    except KeyboardInterrupt:
        print("\nStopping...")
        stop_flag.set()
        sys.exit()
    except Exception as e:
        print(f"An error occurred: {e}", file=sys.stderr)
        stop_flag.set()
        sys.exit(1)

if __name__ == "__main__":
    main()