| --- |
| language: ja |
| license: apache-2.0 |
| library_name: onnx |
| --- |
| |
| # karin v1 — 日本語母音検出 ONNX モデル |
|
|
| 日本語音声からフレーム単位(20ms)で母音ラベルを推定する軽量 ONNX モデルです。\ |
| VOICEROID / AivisSpeech 等のリップシンク非対応 TTS にリップシンクを後付けする用途を想定しています。\ |
| ブラウザ完結(onnxruntime-web)で動作する 11.25 MB の fp16 モデルです。 |
|
|
| ## 仕様 |
|
|
| 本モデルの入出力・サイズ等の主要仕様は以下のとおりです。 |
|
|
| | 項目 | 値 | |
| | --- | --- | |
| | 入力 | `wav` — `[batch, samples]` float32, 16 kHz mono, 値域 [-1, 1] | |
| | 出力 | `logits` — `[1, T, 8]` float32(T = samples // 320 + 1) | |
| | クラス | `a i u e o N cons pau`(後述) | |
| | フレーム長 | 20 ms(hop 320 サンプル @ 16 kHz) | |
| | パラメータ数 | 4.51M | |
| | ファイルサイズ | 11.25 MB(fp16) | |
|
|
| - メル特徴量抽出と CMVN(発話単位正規化)は ONNX グラフ内部にあります。\ |
| ブラウザ側で特徴量計算は不要で、生の 16 kHz mono 波形をそのまま入力できます。 |
| - 入出力テンソルは float32 です(fp16 は重みのみ)。 |
| - 1 発話ずつ入力します(出力は常に batch=1)。 |
|
|
| ## クラス |
|
|
| 出力 logits の 8 クラスは以下のとおりです。 |
|
|
| | Index | ラベル | 説明 | |
| | --- | --- | --- | |
| | 0 | `a` | 母音 /a/ | |
| | 1 | `i` | 母音 /i/ | |
| | 2 | `u` | 母音 /u/ | |
| | 3 | `e` | 母音 /e/ | |
| | 4 | `o` | 母音 /o/ | |
| | 5 | `N` | 撥音 /N/ | |
| | 6 | `cons` | 子音(促音 cl 含む) | |
| | 7 | `pau` | 無音・休止 | |
|
|
| リップシンク用途では `cons` を直後の母音ランへ吸収する後処理が推奨されます。\ |
| 口の動きから子音は視覚上ほぼ識別できず、母音境界を連結することで母音間の遷移が滑らかになります。 |
|
|
| ## 使い方 |
|
|
| Python(onnxruntime)と JavaScript(onnxruntime-web)での最小推論例を示します。 |
|
|
| ### Python(onnxruntime) |
|
|
| ```python |
| import numpy as np |
| import onnxruntime as ort |
| import librosa |
| |
| LABELS = ["a", "i", "u", "e", "o", "N", "cons", "pau"] |
| |
| session = ort.InferenceSession("karin_vowel_v1_fp16.onnx") |
| wav, _ = librosa.load("input.wav", sr=16000, mono=True) |
| logits = session.run(None, {"wav": wav[None, :].astype(np.float32)})[0] |
| frames = logits[0].argmax(axis=-1) # (T,) クラス index |
| labels = [LABELS[i] for i in frames] # 20ms ごとのラベル列 |
| ``` |
|
|
| ### JavaScript(onnxruntime-web) |
|
|
| ```javascript |
| import * as ort from "onnxruntime-web"; |
| |
| const LABELS = ["a", "i", "u", "e", "o", "N", "cons", "pau"]; |
| |
| const session = await ort.InferenceSession.create("karin_vowel_v1_fp16.onnx"); |
| // wav: 事前に取得した Float32Array (16 kHz mono, [-1, 1]) |
| const tensor = new ort.Tensor("float32", wav, [1, wav.length]); |
| const { logits } = await session.run({ wav: tensor }); |
| |
| // logits.data は Float32Array (row-major, shape = [1, T, 8]) |
| const T = logits.dims[1]; |
| const frames = new Array(T); |
| for (let t = 0; t < T; t++) { |
| let best = 0; |
| for (let c = 1; c < 8; c++) { |
| if (logits.data[t * 8 + c] > logits.data[t * 8 + best]) best = c; |
| } |
| frames[t] = best; |
| } |
| const labels = frames.map(i => LABELS[i]); // 20ms ごとのラベル列 |
| ``` |
|
|
| ## 性能評価 |
|
|
| `vowel_only_acc` は母音フレーム(a/i/u/e/o/N)のみで計算したフレーム単位精度です。\ |
| JSUT は本 ONNX の学習に使用していないドメイン、AivisHub は学習データと同一ドメインでの評価です。 |
|
|
| | Domain | Frames | acc | macro_f1 | vowel_f1 | vowel_only_acc | |
| | --- | --- | --- | --- | --- | --- | |
| | JSUT basic5000 (実音声) | 92,859 | 0.9081 | 0.8839 | 0.8854 | 0.9102 | |
| | AivisHub 合成 TTS | 175,259 | 0.8107 | 0.7600 | 0.7750 | 0.8692 | |
|
|
| ## 学習データ |
|
|
| 本モデルの学習に使用したコーパス・音声リソースは以下のとおりです。 |
|
|
| - ReazonSpeech small |
| - つくよみちゃんコーパス Vol.1 |
| - あみたろのITAコーパス読み上げ音声 |
| - AivisHub の ACML 1.0 / CC0 公開モデルによる合成音声 |
|
|
| JSUT は教師プローブの学習 GT と評価用にのみ使用しており、本 ONNX の学習には使用していません。\ |
| 詳細な出典・ライセンスは `NOTICE` ファイルを参照してください。 |
|
|
| ## ライセンス |
|
|
| Apache License 2.0 |
|
|
| 学習データのライセンス・出典は `NOTICE` ファイルに集約してあります。 |
|
|
| ## クレジット・謝辞 |
|
|
| 本モデルの学習に使用したリソース提供元への謝辞を以下に示します。 |
|
|
| - あみたろのITAコーパス読み上げ音声(<https://amitaro.net/voice/corpus-list/ita/>) |
| - つくよみちゃんコーパス(<https://tyc.rei-yumesaki.net/material/corpus/>) |
| - ReazonSpeech(<https://research.reazon.jp/>) |
| - AivisHub(<https://hub.aivis-project.com/>) |
|
|
| ## 組み込みアプリへのお願い |
|
|
| 配布時には同梱の `NOTICE` ファイルの内容を含めてください。 |
|
|