Introdução geral
O insanely-fast-whisper é uma ferramenta de transcrição de áudio que combina o modelo Whisper da OpenAI com várias técnicas de otimização (por exemplo, Transformers, Optimum, Flash Attention) para fornecer uma interface de linha de comando (CLI) projetada para transcrever grandes quantidades de áudio de forma rápida e eficiente. Ele usa o modelo Whisper Large v3 e é capaz de transcrever 150 minutos de conteúdo de áudio em menos de 98 segundos. Os usuários podem obter mais detalhes, guias de instalação e ajuda de uso no repositório do GitHub.
reconhecimento de vários alto-falantes
O pyannote.audio é um kit de ferramentas de código aberto para diarização de alto-falantes escrito em Python. Com base na estrutura de aprendizado de máquina PyTorch, ele apresenta modelos e pipelines pré-treinados de última geração para ajustar ainda mais seus próprios dados e obter melhor desempenho.
faster-whisper + pyannote.audio implementa o reconhecimento de alto-falante, na verdade, simplesmente combinando os resultados dos dois
Armazém oficial: https://github.com/pyannote/pyannote-audio
Lista de funções
Transcrição de áudio usando o modelo Whisper Large v3
Adoção de Transformers, Optimum, Flash Attention e outras tecnologias
Fornece uma interface CLI
Suporte a diferentes tipos de otimização e exibição de benchmarks
Usando a Ajuda
Instalação: Instalação e configuração com o pip
Uso: Passe parâmetros e execute tarefas de transcrição diretamente da linha de comando
Obter ajuda: visite o repositório do GitHub para ler a documentação e conversar com a comunidade.
https://github.com/SYSTRAN/faster-whisper项目编写的código do google colab
# Instalação das bibliotecas necessáriasget_ipython().system('pip install faster-whisper')# Importar as bibliotecas necessáriasfrom faster_whisper import available_modelstocha de importaçãoimportar ipywidgets como widgetsfrom IPython.display import display, clear_outputimport os # Importar bibliotecas do sistema operacional para lidar com operações de arquivosimportar gc # importar biblioteca de coleta de lixo# Detecta automaticamente o tipo de dispositivo e seleciona GPU ou CPUdevice = "cuda" if torch.cuda.is_available() else "cpu"model_size = "large-v2" # Seleção padrão do tamanho do modelocompute_type = "float16" if device == "cuda" else "float32" # Mude para float32 se a CPU for usada# Obtenha uma lista dos modelos disponíveismodels_list = available_models()Lista de idiomas padrão do #supported_languages = ['en', 'fr', 'de', 'zh', '...'] O # usa a lista padrão de idiomasdefault_language = 'zh' if 'zh' in supported_languages else supported_languages[0] # Se 'zh' estiver na lista, use-o como padrão; caso contrário, use o primeiro valor da lista
# Criação de uma interface GUImodel_label = widgets.Label('Select model:')model_dropdown = widgets.Dropdown(options=models_list, value=model_size)language_label = widgets.Label('Language:')language_dropdown = widgets.Dropdown(options=supported_languages, value=default_language)beam_size_label = widgets.Label('Beam size:')beam_size_slider = widgets.IntSlider(value=5, min=1, max=10, step=1)compute_type_label = widgets.Label('Compute type:')se o dispositivo == "cuda".compute_type_options = ['float16', 'int8']e mais.compute_type_options = ['float32'] # Se for CPU, bloquear para float32compute_type_dropdown = widgets.Dropdown(options=compute_type_options, value=compute_type)mode_label = widgets.Label('Format Mode:')mode_dropdown = widgets.Dropdown(options=['normal', 'timeline', 'subtitle'], value='normal')initial_prompt_label = widgets.Label('Initial Prompt:') # Novo rótulo de prompt inicial adicionadoinitial_prompt_text = widgets.Text(value='') # Caixa de entrada de prompt inicial adicionadafile_name_text = widgets.Text(description='File name:', value='/content/') # Permitir que o usuário insira o nome do arquivotranscribe_button = widgets.Button(description='Transcribe')output_area = widgets.Output()
# Definição da função de traduçãodef transcribe_audio(b).com output_area.clear_output()print("Iniciando a transcrição...")from faster_whisper import WhisperModel # Importação dinâmica do WhisperModel: importar quando necessário para economizar RAMtentar.file_name = file_name_text.value # Usar o nome de arquivo inserido pelo usuárioinitial_prompt = initial_prompt_text.value # Prompt inicial usando a entrada do usuário# Garantir que o documento existaif not os.path.exists(nome_do_arquivo):: if not os.path.exists(nome_do_arquivo).print(f "O arquivo {nome_do_arquivo} não existe, verifique se o nome do arquivo e o caminho estão corretos.")retorno# Aquisição de modelos selecionadosselected_model = model_dropdown.valueselected_compute_type = compute_type_dropdown.valueselected_language = language_dropdown.value# Crie uma nova instância de modelo e faça a traduçãomodel = WhisperModel(selected_model, device=device, compute_type=selected_compute_type)tentar.# Áudio traduzidosegments, info = model.transcribe(file_name, beam_size=beam_size_slider.value, language=selected_language, initial_prompt=initial_prompt ) Parâmetros do prompt inicial adicionados ao #Resultados da impressão #print("Idioma detectado '%s' com probabilidade %f" % (info.language, info.language_probability))para segmento em segmentos:se mode_dropdown.value == 'normal'.print("%s " % (segment.text))elif mode_dropdown.value == 'timeline'.print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, segment.text))else: legenda #start_time = "{:02d}:{:02d}:{:02d},{:03d}".format(int(segment.start // 3600), int((segment.start % 3600) // 60), int(segment.start % 60), int((segment.start % 1) * 1000))end_time = "{:02d}:{:02d}:{:02d},{:03d}".format(int(segment.end // 3600), int((segment.end % 3600) // 60), int(segment.end % 60), int((segment. segment.end % 1) * 1000))print("%d\n%s --> %s\n%s\n" % (segment.id, start_time, end_time, segment.text))Finalmente.# Excluir a instância do modelo para liberar a RAMmodelo delexceto Exception como e.print("Ocorreu um erro durante a transcrição:")print(str(e))Finalmente.# Chamando a coleta de lixogc.collect()print("Transcrição concluída.")
Interface GUI do conjunto #display(model_label, model_dropdown, language_label, language_dropdown, beam_size_label, beam_size_slider, compute_type_label, compute_ type_dropdown, mode_label, mode_dropdown, initial_prompt_label, initial_prompt_text, file_name_text, transcribe_button, output_area)transcribe_button.on_click(transcribe_audio)
from pyannote.core import Segment
def get_text_with_timestamp(transcribe_res).
timestamp_texts = [] para item em transcribe_res:
start = item.start
end = item.end
text = item.text.strip()
timestamp_texts.append((Segment(start, end), text))
retornar timestamp_textsdef add_speaker_info_to_text(timestamp_texts, ann)::
spk_text = [] for seg, text in timestamp_texts:
spk = ann.crop(seg).argmax()
spk_text.append((seg, spk, text))
retornar spk_textdef merge_cache(text_cache).
sentença = ''.join([item[-1] for item in text_cache])
spk = text_cache[0][1] start = round(text_cache[0][0].start, 1)
end = round(text_cache[-1][0].end, 1)
return Segment(start, end), spk, sentencePUNC_SENT_END = [',', '.' , '? , '!' , ",", "." , "?" , "!"]
def merge_sentence(spk_text).
merged_spk_text = [] pre_spk = Nenhum
text_cache = [] for seg, spk, text in spk_text:
se spk ! = pre_spk e pre_spk não for None e len(text_cache) > 0:.
merged_spk_text.append(merge_cache(text_cache))
text_cache = [(seg, spk, text)] pre_spk = spkelif text and len(text) > 0 and text[-1] in PUNC_SENT_END:
text_cache.append((seg, spk, text))
merged_spk_text.append(merge_cache(text_cache))
text_cache = [] pre_spk = spk
e mais.
text_cache.append((seg, spk, text))
pre_spk = spk
se len(text_cache) > 0.
merged_spk_text.append(merge_cache(text_cache))
return merged_spk_textdef diarize_text(transcribe_res, diarisation_result).
timestamp_texts = get_text_with_timestamp(transcribe_res)
spk_text = add_speaker_info_to_text(timestamp_texts, diarisation_result)
res_processed = merge_sentence(spk_text)
return res_processeddef write_to_txt(spk_sent, file).
com open(file, 'w') as fp.
para seg, spk, sentence em spk_sent.
line = f'{seg.start:.2f} {seg.end:.2f} {spk} {sentence}\n'
fp.write(line)
tocha de importação
importação sussurro
importar numpy como np
da pydub import AudioSegment
from loguru import logger
from faster_whisper import WhisperModel
de pyannote.audio import Pipeline
from pyannote.audio import Audiode common.error.import ErrorCode
model_path = config["asr"]["faster-whisper-large-v3"]
# Áudio de teste: https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/test_audio/asr_speaker_demo.wav
audio = ". /test/asr/data/asr_speaker_demo.wav"
asr_model = WhisperModel(model_path, device="cuda", compute_type="float16")
spk_rec_pipeline = Pipeline.from_pretrained("pyannote/speaker-diarisation-3.1", use_auth_token="your huggingface token")
spk_rec_pipeline.to(torch.device("cuda"))asr_result, info = asr_model.transcribe(audio, language="zh", beam_size=5)
diarisation_result = spk_rec_pipeline(audio)final_result = diarize_text(asr_result, diarisation_result)
para segmento, spk, enviado em final_result:
print("[%.2fs -> %.2fs] %s %s" % (segment.start, segment.end, sent, spk))
Recursos relacionados
Projeto principal: https://github.com/SYSTRAN/faster-whisper
Código abreviado: https://www.letswrite.tw/colab-faster-whisper/
Vídeo do Tube para legendas: https://github.com/lewangdev/faster-whisper-youtube
Transcrição de voz em tempo real do Fast Whisper: https://www.kaggle.com/code/xiu0714/faster-whisper