вот мой код #! python3.8>

import csv import os

import gigaam import speech_recognition as sr from queue import Queue from time import sleep import torch from pyctcdecode import build_ctcdecoder from datetime import datetime, timedelta import wave

import nemo.collections.asr as nemo_asr
import tkinter as tk # Импорт Tkinter для работы с GUI

from nemo.collections.asr.modules.audio_preprocessing import (
AudioToMelSpectrogramPreprocessor as NeMoAudioToMelSpectrogramPreprocessor,
)
from nemo.collections.asr.parts.preprocessing.features import (
FilterbankFeaturesTA as NeMoFilterbankFeaturesTA,
)
TODO: буфер гигаам через pyctcdecode (чтобы не сохранять в файл звук)
gmodel = gigaam.load_model("v2_ctc", device="cuda").eval()
vocab = gmodel.decoding.tokenizer.vocab
decoder = pyctcdecode.build_ctcdecoder(
vocab,
"vosk-model-lm/ru.lm.bin",
alpha=0.5, beta=1.0
)
def recognize_giga(alldata, sr):
wav = torch.frombuffer(bytearray(alldata), dtype=torch.int16).float() / 32768.0
wav = wav.unsqueeze(0)
wav = torchaudio.functional.resample(wav, sr, 16000).cuda()
length = torch.full([1], wav.shape[-1], device=wav.device)
encoded, encoded_len = gmodel.forward(wav, length)
logits = gmodel.head(encoded).squeeze().detach().cpu().numpy()
transcript = decoder.decode_beams(logits, beam_width=100)
print (transcript)
import torchaudio import warnings

warnings.simplefilter(action="ignore", category=FutureWarning) warnings.simplefilter(action="ignore", category=UserWarning)

class RealtimeASR: def init(self): self.num_channels = 1 # Моно = 1, Стерео = 2 self.sample_width = 2 # Количество байт на сэмпл, например, 16-битное аудио = 2 байта self.frame_rate = 16000 # Частота дискретизации (количество фреймов в секунду)

    self.energy_threshold = 70
    self.record_timeout = 3
    self.phrase_timeout = 0.6
    self.default_microphone = 'pulse'
    self.phrase_time = None
    self.data_queue = Queue()

    self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
    self.model_config = 'gigaam/rnnt_model_config.yaml'
    self.model_weights = 'gigaam/rnnt_model_weights.ckpt'

    self.load_model()

    self.transcription = ['']
    self.count_files = len(os.listdir('csv_nemo_speak'))

def load_model(self):
    self.model = gigaam.load_model(
        "rnnt",  # GigaAM-V2 RNNT model
        # fp16_encoder=True,  # to use fp16 encoder weights - GPU only
        # use_flash=True,
        device="cuda",  # CPU-inference
    )

def save_audio(self, audio_bytes):
    # Открыть файл для записи
    with wave.open('output.wav', 'wb') as wf:
        wf.setnchannels(self.num_channels)
        wf.setsampwidth(self.sample_width)
        wf.setframerate(self.frame_rate)
        wf.writeframes(audio_bytes)

def initialize_tkinter_window(self):
    self.root = tk.Tk()
    self.root.title("Transcription")

    # set params tkinter
    # Создание фрейма для группировки Text и Scrollbar вместе
    frame = tk.Frame(self.root)
    frame.pack(expand=True, fill='both')  # Фрейм будет расширяться и заполнять окно
    # Создание виджета текста с настройками
    self.transcription_text = tk.Text(frame, state='disabled', wrap='word')
    self.transcription_text.pack(side=tk.LEFT, expand=True, fill='both')
    # Создание скроллбара
    scrollbar = tk.Scrollbar(frame, command=self.transcription_text.yview)
    scrollbar.pack(side=tk.RIGHT, fill='y')  # Размещение скроллбара справа от Text, заполнение по вертикали
    # Настройка виджета Text для работы со скроллбаром
    self.transcription_text.config(yscrollcommand=scrollbar.set)

    self.root.update()

def update_transcription_window(self):
    """
    Обновляет текст в окне Tkinter.
    """
    self.transcription_text.config(state=tk.NORMAL)  # Разрешить редактирование виджета текста
    # transcription_text.delete('1.0', tk.END)  # Очистить текущий текст
    self.transcription_text.config(font=("Courier", 14))  # Установить более крупный шрифт
    # for char in text:
    self.transcription_text.insert(tk.END, self.transcription[-1] + ' ')
    if len(self.transcription) % 3 == 0:
        self.transcription_text.insert(tk.END, '\n')
    # Вставить один символ
    self.transcription_text.update()  # Обновить окно Tkinter
    # sleep(0.01)  # Задержка в 0.05 секунды между символами

    self.transcription_text.see(tk.END)
    self.transcription_text.config(state=tk.DISABLED)  # Запретить редактирование виджета текста
    self.root.update()  # Обновить окно Tkinter

def record_callback(self, _, audio: sr.AudioData) -> None:
    """
    Threaded callback function to receive audio data when recordings finish.
    audio: An AudioData containing the recorded bytes.
    """
    # Grab the raw bytes and push it into the thread safe queue.
    data = audio.get_raw_data()
    self.data_queue.put(data)

def inference(self):

    # init tkinter window
    self.initialize_tkinter_window()

    # init recorder
    recorder = sr.Recognizer()
    recorder.energy_threshold = self.energy_threshold
    recorder.dynamic_energy_threshold = False

    mic_name = self.default_microphone
    for index, name in enumerate(sr.Microphone.list_microphone_names()):
        if mic_name in name:
            source = sr.Microphone(sample_rate=16000, device_index=index)
            break

    with source:
        recorder.adjust_for_ambient_noise(source)

    recorder.listen_in_background(source, self.record_callback, phrase_time_limit=self.record_timeout)
    print("Start streaming")
    last_transcription = []
    while True:
        try:
            now = datetime.utcnow()
            if not self.data_queue.empty():
                phrase_complete = False
                if self.phrase_time and now - self.phrase_time > timedelta(seconds=self.phrase_timeout):
                    phrase_complete = True
                # This is the last time we received new audio data from the queue.
                self.phrase_time = now

                # Combine audio data from queue
                audio_bytes = b''.join(self.data_queue.queue)
                self.data_queue.queue.clear()

                self.save_audio(audio_bytes)

                transcript_pred = self.model.transcribe('output.wav')

                text = transcript_pred
                print(text)

                # If we detected a pause between recordings, add a new item to our transcription.
                # Otherwise edit the existing one.
                if self.transcription[-1] != text and text != ' ' and text != '' and text[0] != '':
                    self.transcription.append(text)
                    print(self.transcription)
                    if len(self.transcription) != 0:
                        self.update_transcription_window()  # Обновить текст в окне Tkinter
                        print(text)

                # Clear the console to reprint the updated transcription.
                os.system('cls' if os.name == 'nt' else 'clear')

                # Infinite loops are bad for processors, must sleep.
                sleep(0.20)

                with open(f'./csv_nemo_speak/output_{self.count_files}.csv', 'w', newline='', encoding='utf-8') as csvfile:
                    csvwriter = csv.writer(csvfile)
                    csvwriter.writerow(self.transcription)

                # last_text = self.transcription_text[-1]
                last_transcription = self.transcription
        except KeyboardInterrupt:
            break
if name == "main": gigaam = RealtimeASR() gigaam.inference()

проанализируй код и что можно улучшить - напиши список зачем почему. а также улучши мой код tkinter чтобы все было красиво и понятно. если что - это код который я запускаю когда веду разговоры по видеоконференцсвязи, звук поступает из колонок в микрофон ноутбука и транскрибирует в рил тайме. я слабослыщащая поэтому это помогает мне понимать что мне говорят.