Whisperで ひらがな、カタカナ のみ出力させる

# 概要
Whisperでひらがな、カタカナ のみ出力させるようにしたい
# 結果

```
原文
また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。

ひらがな　カタカナ
また、とうじのようにごだいみょうおうとよばれるしようなみょうおうのちうおうにはいされることもおおい
```

# 方策
1. コマンドオプションの --suppress_tokens を使う
2. トークンを生成するデーコーダを編集して、推論時のひらがな、カタカナ以外の選択を抑制する

今回はsuppress_tokensだけを利用していく。

# 環境 
Windows 11
Python3.10
git
グラフィックボードなし

# 事前準備
```powershell

 # 仮想環境
 python -m venv venv
 .\venv\Scripts\activate

# ライブラリインストール
 pip install numpy torch

 # Whisper ダウンロード
 pip install  git+https://github.com/openai/whisper.git

```

FFmpegをインストールしてPathを通しておく
https://ffmpeg.org/

# 検証用音声
■つくよみちゃんコーパス（CV.夢前黎）
https://tyc.rei-yumesaki.net/material/corpus/

つくよみちゃんコーパス Vol.1 声優統計コーパス（JVSコーパス準拠）
VOICEACTRESS100_001.wav

## 原文書き起こし
```text:VOICEACTRESS100_001.wav 台本
また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。
```


# コマンドオプション --suppress_tokens の利用
suppress_tokens：カンマで区切られた、サンプリング時に抑止するトークンIDのリスト

tokens_to_ignore.txtにひらがな、カタカナ以外のトークンIDを保存し、このファイルを読み込み、ひらがな、カタカナ以外の生成を抑制するプログラムを作成する。


```python:whisper01.py
import whisper

# Whisperモデルのロード
model = whisper.load_model("medium")

# 音声ファイルの読み込みと30秒に収める処理
audio = whisper.load_audio("VOICEACTRESS100_001.wav")
audio = whisper.pad_or_trim(audio)

# メルスペクトログラムを作成し、モデルと同じデバイスに移動
mel = whisper.log_mel_spectrogram(audio, n_mels=model.dims.n_mels).to(model.device)

# ファイルから無視するトークンを読み込む
def load_suppress_tokens(file_path):
    with open(file_path, 'r', encoding='utf-8') as f:
        # ファイルからトークンを読み込み、リストに変換（空白または改行で区切られた数値）
        tokens = f.read().split()
        # 各トークンを整数に変換して返す
        return [int(token) for token in tokens]

# suppress_tokens ファイルからトークンIDを読み込む
suppress_tokens = load_suppress_tokens("tokens_to_ignore.txt")

# デコードオプションに suppress_tokens を設定
options = whisper.DecodingOptions(language="ja", suppress_tokens=suppress_tokens, beam_size=3)

# 音声をデコード
result = whisper.decode(model, mel, options)

# 結果を表示
print("Transcription:", result.text)

# 結果をファイルに保存
with open("transcription_result.txt", "w", encoding="utf-8") as f:
    f.write(result.text)

print("文字起こしが完了しました。結果は 'transcription_result.txt' に保存されました。")

```

```text:tokens_to_ignore.txt
0
1
2
3
4

.
.
.

50250
50251
50252
50253
50254
50255
50256

```

tokens_to_ignore.txtを生成するプログラム

```create_ignore_tokens.py
import base64
import re

# multilingual.tiktoken ファイルのパス
token_file_path = "multilingual.tiktoken"

# 全角ひらがなカタカナおよび句読点判定用の関数
def is_katakana_or_punctuation(text):
    return bool(re.match(r'^[\u3000-\u30FF、。]+$', text))

# multilingual.tiktokenファイルを読み込み、デコードしてトークンIDを取得する
def load_tokens(file_path):
    tokens = []
    with open(file_path, 'r', encoding='utf-8') as file:
        for line in file:
            base64_token, token_id = line.strip().split()
            decoded_token = base64.b64decode(base64_token).decode('utf-8', errors='ignore')
            tokens.append((decoded_token, int(token_id)))
    return tokens

# カタカナおよび句読点以外のトークンを無視するためのトークンIDリストを作成
def get_non_katakana_or_punctuation_tokens(tokens):
    non_katakana_or_punctuation_tokens = []
    for token, token_id in tokens:
        if not is_katakana_or_punctuation(token):  # カタカナおよび句読点でない場合
            non_katakana_or_punctuation_tokens.append(token_id)
    return non_katakana_or_punctuation_tokens

# トークンIDをファイルに書き出す
def save_tokens_to_file(tokens, output_file_path):
    with open(output_file_path, 'w', encoding='utf-8') as file:
        for token_id in tokens:
            file.write(f"{token_id}\n")

# トークンを読み込む
tokens = load_tokens(token_file_path)

# カタカナおよび句読点以外のトークンIDを取得
non_katakana_or_punctuation_tokens = get_non_katakana_or_punctuation_tokens(tokens)

# 無視するトークンIDリストをファイルに保存
save_tokens_to_file(non_katakana_or_punctuation_tokens, "tokens_to_ignore.txt")

print("カタカナおよび句読点以外のトークンIDが 'tokens_to_ignore.txt' に保存されました。")


```


※追記
multilingual.tiktokenのダウンロード　↓
https://github.com/openai/whisper/blob/main/whisper/assets/gpt2.tiktoken
gpt2.tiktokenをmultilingual.tiktokenに名前変更

また、完全なひらがなと句読点のみにしたい場合↓（動作未確認）
```create_ignore_tokens.py
# ひらがなと句読点、伸ばし棒のみ
def is_katakana_or_punctuation(text):
    return bool(re.match(r'^[\u3041-\u308D\u308F\u3092\u3093\u3001\u3002\u30FC]+$', text))

```
## 結果
```powershell:出力
(venv) PS C:\workspase\01python> python .\whisper01.py
Transcription: また、とうじのようにごだいみょうおうとよばれるしようなみょうおうのちうおうにはいされることもおおい
文字起こしが完了しました。結果は 'transcription_result.txt' に保存されました。
```

### 結果比較

```
原文
また、東寺のように、五大明王と呼ばれる、主要な明王の中央に配されることも多い。

ひらがな　カタカナ
また、とうじのようにごだいみょうおうとよばれるしようなみょうおうのちうおうにはいされることもおおい
```

「中央」が「ちうおう」になっているなど、少しくずれているぶぶんもある



# 参考
Github Whisper 
https://github.com/openai/whisper

検証音源
■つくよみちゃんコーパス（CV.夢前黎）
https://tyc.rei-yumesaki.net/material/corpus/

Pythonで音声認識を簡単に！Whisperライブラリの使い方完全ガイド
https://qiita.com/automation2025/items/a2a21cc7d41279c495be


Zenn:WhisperのREADME
https://zenn.dev/piment/articles/ca917d0e9c8a49

OpenAI Whisper のコマンドオプション
https://qiita.com/szktmyk38f/items/374f24d06fe277a1922a

Unicode 内のそれぞれの文字種の範囲
https://pages.michinobu.jp/t/misc/unicodecodechars.html