--- 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コーパス読み上げ音声() - つくよみちゃんコーパス() - ReazonSpeech() - AivisHub() ## 組み込みアプリへのお願い 配布時には同梱の `NOTICE` ファイルの内容を含めてください。