はじめに
insanely-fast-whisperは、OpenAIのWhisperモデルと様々な最適化技術(Transformers、Optimum、Flash Attentionなど)を組み合わせた音声書き起こしツールで、大量の音声を迅速かつ効率的に書き起こすために設計されたコマンドラインインターフェース(CLI)を提供します。Whisper Large v3モデルを使用し、150分の音声コンテンツを98秒以内で書き起こすことができます。ユーザーは、GitHubリポジトリから、詳細、インストールガイド、使用法のヘルプを学ぶことができます。
マルチスピーカー認識
pyannote.audioは、Pythonで書かれたスピーカーの日記のためのオープンソースのツールキットです。PyTorch機械学習フレームワークに基づいており、最先端の事前学習済みモデルと、より良いパフォーマンスのために独自のデータをさらに微調整するためのパイプラインを備えています。
faster-whisper + pyannote.audioは、2つの結果を単純に組み合わせることで、実際、話者認識を実装している。
公式倉庫:https://github.com/pyannote/pyannote-audio
機能一覧
Whisper Large v3モデルによる音声転写
トランスフォーマー、オプティマム、フラッシュ・アテンション、その他のテクノロジーの採用
CLIインターフェースを提供
さまざまな最適化タイプをサポートし、ベンチマークを表示
ヘルプの使用
インストール:pipによるインストールと設定
使用法: パラメータを渡し、コマンドラインから直接転写タスクを実行する。
ヘルプを入手する: GitHubのリポジトリでドキュメントを参照し、コミュニティで交流しましょう。
https://github.com/SYSTRAN/faster-whisper项目编写的グーグルコラボコード
# 必要なライブラリのインストールget_ipython().system('pip install faster-whisper')# 必要なライブラリをインポートするfrom faster_whisper import available_models輸入トーチウィジェットとしてipywidgetsをインポートするfrom IPython.display import display, clear_outputimport os # ファイル操作を処理するためのオペレーティング・システム・ライブラリをインポートする。インポート gc # インポート ゴミ収集ライブラリ# デバイスの種類を自動的に検出し、GPUまたはCPUを選択します。device = "cuda" if torch.cuda.is_available() else "cpu"model_size = "large-v2" # モデルサイズのデフォルト選択compute_type = "float16" if device == "cuda" else "float32" # CPUが使用されている場合、float32に切り替える。# 利用可能なモデルのリストを取得するmodels_list = available_models()# デフォルト言語リストsupported_languages = ['en', 'fr', 'de', 'zh', '...'] となります。 #はデフォルトの言語リストを使用します。default_language = 'zh' if 'zh' in supported_languages else supported_languages[0] # 'zh'がリストにあれば、それをデフォルトとする。
# GUIインターフェースの作成model_label = widgets.Label('モデルを選択:')model_dropdown = widgets.Dropdown(options=models_list, value=model_size)language_label = widgets.Label('言語:')language_dropdown = widgets.Dropdown(options=supported_languages, value=default_language)beam_size_label = widgets.Label('ビームサイズ:')beam_size_slider = widgets.IntSlider(value=5, min=1, max=10, step=1)compute_type_label = widgets.Label('計算タイプ:')if device == "cuda".compute_type_options = ['float16', 'int8'].そうでなければcompute_type_options = ['float32'] # CPUならfloat32にロックする。compute_type_dropdown = widgets.Dropdown(options=compute_type_options, value=compute_type)mode_label = widgets.Label('フォーマットモード:')mode_dropdown = widgets.Dropdown(options=['normal', 'timeline', 'subtitle'], value='normal')initial_prompt_label = widgets.Label('Initial Prompt:') # 新しい初期プロンプトラベルが追加されました。initial_prompt_text = widgets.Text(value='') # 初期プロンプト入力ボックス追加file_name_text = widgets.Text(description='File name:', value='/content/') # ユーザーがファイル名を入力できるようにする。transcribe_button = widgets.Button(description='Transcribe')output_area = widgets.Output()
# 翻訳機能の定義def transcribe_audio(b).をoutput_areaとする。clear_output()print("転写の開始...")from faster_whisper import WhisperModel # WhisperModelの動的インポート:RAMを節約するために必要なときにインポートする。トライしてみよう。file_name = file_name_text.value # ユーザーが入力したファイル名を使用する。initial_prompt = initial_prompt_text.value # ユーザー入力による初期プロンプト# 文書が存在することを確認するif not os.path.exists(file_name): if not os.path.exists(file_name).print(f "ファイル{ファイル名}が存在しません。ファイル名とパスが正しいか確認してください。")戻る# 特定機種の取得selected_model = model_dropdown.valueselected_compute_type = compute_type_dropdown.valueselected_language = language_dropdown.value# 新しいモデルインスタンスを作成し、翻訳を行うmodel = WhisperModel(selected_model, device=device, compute_type=selected_compute_type)トライしてみよう。#翻訳オーディオsegments, info = model.transcribe(ファイル名, beam_size=beam_size_slider.value, language=selected_language, initial_prompt=initial_prompt) #に追加された初期プロンプト・パラメータ# 印刷結果print("Detected language '%s' with probability %f" % (info.language, info.language_probability))for segment in segments:mode_dropdown.value == 'normal'.print("%s " % (segment.text))elif mode_dropdown.value == 'timeline'.print("[%.2fs -> %.2fs] %s" % (segment.start, segment.end, segment.text))else: #字幕start_time = "{:02d}:{:02d}:{:02d},{:03d}".format(int(segment.start // 3600), int((segment.start % 3600) // 60), int(segment.start ), 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.セグメント.エンド % 1) * 1000))print("%dn%s --> %sn%sn" % (segment.id, start_time, end_time, segment.text))最後に# モデルインスタンスを削除してRAMを空けるデルモデル例外を除く。print("転写中にエラーが発生しました:")print(str(e))最後に# ガベージコレクションの呼び出しgc.collect()print("トランスクリプションが完了しました。")
#アセンブリGUIインターフェース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)
pyannote.core import セグメント
def get_text_with_timestamp(transcribe_res).
timestamp_texts = []
for item in transcribe_res:
start = item.start
end = item.end
text = item.text.strip()
timestamp_texts.append((Segment(start, end), text))
return 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))
return spk_textdef merge_cache(text_cache).
sentence = ''.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)
戻り値 Segment(start, end), spk, sentencepunc_sent_end = [',', '., '?, '!', ",", ".", "?", "!"]
def merge_sentence(spk_text).
merged_spk_text = [].
pre_spk = なし
text_cache = [].
for seg, spk, text in spk_text:
if spk != pre_spk かつ pre_spk が None でなく 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
そうでなければ
text_cache.append((seg, spk, text))
pre_spk = spk
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).
with open(file, 'w') as fp.
for seg, spk, sentence in spk_sent.
line = f'{seg.start:.2f} {seg.end:.2f} {spk} {sentence}n'
fp.write(line)
輸入トーチ
インポート・ウィスパー
npとしてnumpyをインポートする
pydub import AudioSegment
from loguru import logger
from faster_whisper import WhisperModel
pyannote.audio import パイプライン
pyannote.audio import オーディオfrom common.error.import ErrorCode
model_path = config["asr"]["faster-whisper-large-v3"].
# テスト・オーディオ: 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 トークン")
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)
for segment, spk, sent in final_result:
print("[%.2fs -> %.2fs] %s %s" % (segment.start, segment.end, sent, spk))