Closed8

話者分離と音声認識 (定番のpyannote.audioでなくNeMoのdiarization modelを利用)+日本語化

moriokamorioka

ネット上を眺めると、python環境での話者分離には pyannote.audio を使うのが通例になっている。
ただ、pyannote.audioの利用にはhuggingface発行のトークンを使う必要がある。オフラインで利用できなくもないが、その準備が面倒だ。

https://dev.classmethod.jp/articles/pyannote-audio-offline/
https://tech-useit-wealth.com/faster-whisper-pyannote
https://qiita.com/HiroHiroPy/items/b3325ff93e3260aa602b
https://zenn.dev/geniee/articles/audio-diarization-transcript-202505003

これ以外の選択肢はないか? .... ある

https://github.com/MahmoudAshraf97/whisper-diarization

moriokamorioka

whisper-diarizationのコードは、6c9047dd7334c48acde62042890fd357117a9f55 (2025/02/05現在)。

cuDNN9のシンボルがない旨のエラーで終わる。

以下に従う。ctranslate2==4.5.0 が cuDNN 9.2に密結合しているので、ダウングレードする。

https://github.com/m-bain/whisperX/issues/901

Here the culprit is ctranslate2. The library was just updated to version 4.5.0, which uses
cuDNN 9.2. Downgrading ctranslate to version 4.4.0 is enough to fix the problem,

# Ubuntu22.04/WSL2 + CUDA12
sudo apt update && sudo apt install cython3
sudo apt update && sudo apt install ffmpeg

# パッケージをインストール
pip install -c constraints.txt -r requirements.txt

# ctranslate2 を 4.5.0 より以前にダウングレード
pip install ctranslate2==4.4.0

# サンプル音声を入手
wget https://huggingface.co/kotoba-tech/kotoba-whisper-v2.2/resolve/main/sample_audio/sample_diarization_japanese.mp3

# 話者分離
python diarize.py  -a sample_diarization_japanese.mp3

動いた。英語のモデルで、英語前提らしい。英語に翻訳されている。

$ more sample_diarization_japanese.txt
Speaker 0: So this is almost like a little jib on the kangkaku taking a day job high skill.  No more email.  Oh, cool.  I know kiyo.  She don't know.  You must cook in real life.  Okay, they were high school.

Speaker 1: I think you must go to a place on a machine.  Oh, I feel is the good news.  Oh, you see, not doing at the weather for your PR section.

Speaker 2: That's your name.  Mizzo, Malaysia.  Cara, kawanak to another notice.
$ more sample_diarization_japanese.srt
1
00:00:00,220 --> 00:00:04,956
Speaker 0: So this is almost like a little jib on the kangkaku taking a day job high skill.

2
00:00:05,082 --> 00:00:06,111
Speaker 0: No more email.

3
00:00:06,174 --> 00:00:06,909
Speaker 0: Oh, cool.

4
00:00:07,119 --> 00:00:07,854
Speaker 0: I know kiyo.

5
00:00:08,379 --> 00:00:09,261
Speaker 0: She don't know.

6
00:00:09,303 --> 00:00:11,634
Speaker 0: You must cook in real life.

7
00:00:12,411 --> 00:00:13,482
Speaker 0: Okay, they were high school.

8
00:00:13,545 --> 00:00:16,422
Speaker 1: I think you must go to a place on a machine.

9
00:00:16,884 --> 00:00:18,144
Speaker 1: Oh, I feel is the good news.

10
00:00:18,186 --> 00:00:21,840
Speaker 1: Oh, you see, not doing at the weather for your PR section.

11
00:00:21,882 --> 00:00:23,436
Speaker 2: That's your name.

12
00:00:23,478 --> 00:00:24,276
Speaker 2: Mizzo, Malaysia.

13
00:00:24,381 --> 00:00:27,909
Speaker 2: Cara, kawanak to another notice.

moriokamorioka

日本語で

$ python diarize.py  --whisper-model large --language ja -a sample_diarization_japanese.mp3
$ more sample_diarization_japanese.txt
Speaker 1: そ う で す ね こ れ も 先 ほ ど ず っ と 言 っ て い る 自 分 の 感 覚 的 に は 大 丈 夫 で す け れ ど も も う 今 は 屋 外 の 気 温 昼 も 夜 も 上 が っ て ま す の で 空 気 の 入 れ 替 え だ け で は か え っ て 人 が
 上 が っ

Speaker 2: て き ま す や っ ぱ り 愚 直 に や っ ぱ り そ の 街 の 良 さ を ア ピ ー ル し て い く っ て い う そ う い う 姿 勢 が 基 本 に あ っ た 上 で の こ う い う P R 作 戦

Speaker 0: だ と 思 う ん で す よ ね 水 を マ レ ー シ ア か ら 買 わ な く て は な ら な い の で す
$ more sample_diarization_japanese.srt
1
00:00:00,220 --> 00:00:13,671
Speaker 1: そ う で す ね こ れ も 先 ほ ど ず っ と 言 っ て い る 自 分 の 感 覚 的 に は 大 丈 夫 で す け れ ど も も う 今 は 屋 外 の 気 温 昼 も 夜 も 上 が っ て ま す の で 空 気 の 入 れ 替 え だ け で は か え っ て 人 が
 上 が っ

2
00:00:13,713 --> 00:00:21,840
Speaker 2: て き ま す や っ ぱ り 愚 直 に や っ ぱ り そ の 街 の 良 さ を ア ピ ー ル し て い く っ て い う そ う い う 姿 勢 が 基 本 に あ っ た 上 で の こ う い う P R 作 戦

3
00:00:21,882 --> 00:00:27,909
Speaker 0: だ と 思 う ん で す よ ね 水 を マ レ ー シ ア か ら 買 わ な く て は な ら な い の で す

タイムスロットのようなものがあるのか、文末が、次の話者にまたがっている印象。

WARNING:root:Punctuation restoration is not available for ja language. Using the original punctuation.

実行中、上記のメッセージが出力されているので、日本語のpunctuationは上手ではないのかもしれない。

moriokamorioka

punctuationを別モデルにさせればよいのだろうな。

moriokamorioka

(別スクラップから転記)2025-02-13 17:11

https://zenn.dev/morioka/scraps/b13316c2660ed0

punctuationモデルが日本語対応していないので、話者ごとの発話末尾の切り出しがうまくない。

使われているpunctuationモデルを日本語対応させるか、日本語対応のpunctuationモデルで差し替えるか。後者で考えてみる。

https://hashicco.hatenablog.com/entry/2024/04/09/195211
https://huggingface.co/bobfromjapan/bert_japanese_punctuation

↑これをつかって、インタフェースを合わせこんでやればよいだろうか。

moriokamorioka

(別スクラップから転記)2025-06-10 00:17

差し替えてみた。しかし、よく見ると差し替えても意味がない。

日本語の文区切りは入るようになったが、話者分離の区切りは変わらない。
よって、日本語文の途中で話者が切り替わるように判断されてしまう。

これは現状のdiarizationモデルの限界なのだろう。

Known Limitationsの一つ目がそれか。

Overlapping speakers are yet to be addressed, a possible approach would be to separate the audio file and isolate only one speaker, then feed it into the pipeline but this will need much more computation

Speaker 1: そ う で す ね。 こ れ も 先 ほ ど ず っ と 言 っ て い る 自 分 の 感 覚 的 に は 大 丈 夫 で す。 け れ ど も 今 は 屋 外 の 気 温 昼 も 夜 も 上 が っ て ま す の で 空 気 の 入 れ 替 え だ け で は か え っ て 人 が 上 が っ  

Speaker 2: て き ま す。 や っ ぱ り 愚 直 に や っ ぱ り そ の 街 の 良 さ を ア ピ ー ル し て い く っ て い う そ う い う 姿 勢 が 基 本 に あ っ た 上 で の こ  

Speaker 1: う い う P R 作 戦  

Speaker 0: だ と 思 う ん で す よ ね。 水 を マ レ ー シ ア か ら 買 わ な く て は な ら な い の で す。
1
00:00:00,220 --> 00:00:13,671
Speaker 1: そ う で す ね。 こ れ も 先 ほ ど ず っ と 言 っ て い る 自 分 の 感 覚 的 に は 大 丈 夫 で す。 け れ ど も 今 は 屋 外 の 気 温 昼 も 夜 も 上 が っ て ま す の で 空 気 の 入 れ 替 え だ け で は か え っ て 人 が 上 が っ

2
00:00:13,713 --> 00:00:20,958
Speaker 2: て き ま す。 や っ ぱ り 愚 直 に や っ ぱ り そ の 街 の 良 さ を ア ピ ー ル し て い く っ て い う そ う い う 姿 勢 が 基 本 に あ っ た 上 で の こ

3
00:00:21,000 --> 00:00:21,840
Speaker 1: う い う P R 作 戦

4
00:00:21,882 --> 00:00:27,909
Speaker 0: だ と 思 う ん で す よ ね。 水 を マ レ ー シ ア か ら 買 わ な く て は な ら な い の で す。

moriokamorioka

(別スクラップから転記)2025-06-11 21:13

これは現状のdiarizationモデルの限界なのだろう。

まちがい。punctuationの結果で アライメントを取り直させる必要があった。その際の文末判断や、処理対象の長さ設定を見直す必要があった。

if info.language in ["ja"]:  # 日本語は1語=1文字で出力されるので、1文あたりの最大語数を多めにとる
    helpers.sentence_ending_punctuations = [".","?","!","。","?","!"]
    wsm = get_realigned_ws_mapping_with_punctuation(wsm,max_words_in_sentence=1500) 
else:
    wsm = get_realigned_ws_mapping_with_punctuation(wsm)
ssm = get_sentences_speaker_mapping(wsm, speaker_ts)

結果は期待通り。

1
00:00:00,220 --> 00:00:14,175
Speaker 1: そ う で す ね。 こ れ も 先 ほ ど が ず っ と 言 っ て い る 自 分 の 感 覚 的 に は 大 丈 夫 で す け れ ど も も う 今 は 屋 外 の 気 温 昼 も 夜 も 上 が っ て ま す の で 空 気 の 入 れ 替 え だ け で は か え っ て 人 が 上 が っ て き ま す。

2
00:00:14,217 --> 00:00:22,680
Speaker 2: や っ ぱ り 愚 直 に や っ ぱ り そ の 街 の 良 さ を ア ピ ー ル し て い く っ て い う そ う い う 姿 勢 が 基 本 に あ っ た 上 で の こ う い う P R 作 戦 だ と 思 う ん で す よ ね。

3
00:00:23,394 --> 00:00:27,909
Speaker 0: 水 を マ レ ー シ ア か ら 買 わ な く て は な ら な い の で す。

コードはgithubにforkして。

https://github.com/morioka/whisper-diarization

このスクラップは3ヶ月前にクローズされました