suzuna / state kotoha ph3x v2

Suzuna — STATE Ph3.x-v2 録音品質UI / RVC学習適性ワークステーション

概要

Phase 1〜3で構築した変換・学習・TTSパイプラインに、 録音品質を担保するための前処理UIを追加する。

コンセプト:「AIを賢くする」ではなく「ユーザーを失敗させない」

単なる録音補助ではなく、RVC学習データの品質を底上げする 「RVC学習適性ワークステーション」として設計する。


アーキテクチャ

ブラウザ側(Web Audio API)
  getUserMedia → MediaStream
    ├── AnalyserNode → リアルタイム波形・音量メーター(canvas)
    └── MediaRecorder → 録音 WAV

Python側(ファイル処理のみ)
  POST /audio/score      → 学習適性スコア算出
  POST /audio/process    → 前処理適用
  POST /audio/env-check  → 環境音評価(3秒WAVを受け取り判定)

音声処理パイプライン

録音 / インポート

① 無音トリミング        (自動)

② ノイズリダクション    (自動 / 強度調整可)

③ ローカット / ハイカット(デフォルト値あり / スライダー調整可)

④ ゲイン調整            (オートノーマライズ or 手動)

⑤ 学習適性スコア表示    (自動算出)

学習データとして保存 / RVC変換へ

重要: パイプライン順序は変更しないこと NR前にゲインするとノイズまで増幅して音質が劣化する。


UI構成

サイドバー順

声質変換     (Ph1)
音声前処理   (Ph3.x) ← ここ
モデル学習   (Ph2)
TTSスタジオ  (Ph3)

録音パネル

┌─ 録音 ────────────────────────────────────────┐
│  [🎤 録音開始]                                  │
│                                                 │
│  波形: ▁▂▄▆▄▂▁▃▅▃▁  (リアルタイム)           │
│  ← 緑=適正 / 黄=小さい / 赤=クリッピング        │
│                                                 │
│  音量: [████████░░] -12dB  ← 適正              │
│        ⚠ クリッピング警告  / ⚠ 小さすぎ警告    │
│                                                 │
│  環境音: 静か ✅  / ノイズ多め ⚠ / 大きい ❌   │
└─────────────────────────────────────────────────┘

波形カラーリング(CSSのみで実装)

状態条件
適正--color-primary(グリーン)-24〜-6dB
小さい--color-warning(橙)-24dB以下
クリッピング--color-error(赤)-3dB以上

録音前環境音チェック(マイク接続時に自動実行)

  • 3秒間の環境音を計測
  • ノイズレベルを判定 → UIバッジ表示
    • ✅ 静か(-50dB以下)
    • ⚠ ノイズあり(-50〜-35dB)
    • ❌ 大きい(-35dB以上)

音声処理パネル

┌─ 音声処理 ─────────────────────────────────────┐
│  入力: voice_001.wav  [▶試聴]                   │
│                                                 │
│  [✅ 無音トリミング]  自動検出・除去             │
│                                                 │
│  ノイズリダクション                  強度: 0.5  │
│  [──────●──────────]                           │
│                                                 │
│  ローカット                          80 Hz      │
│  [●───────────────]  20〜500Hz                 │
│                                                 │
│  ハイカット                         16000 Hz    │
│  [──────────────●─]  8k〜24kHz                 │
│                                                 │
│  ゲイン調整                                     │
│  ○ オートノーマライズ(ピーク -3dB)            │
│  ○ 手動  [──●──────]  +0.0 dB  (-12〜+12)     │
│                                                 │
│  [▶ 処理を適用]  [↩ リセット]                  │
│                                                 │
│  出力: voice_001_processed.wav  [▶試聴]         │
└─────────────────────────────────────────────────┘

RVC学習適性スコアパネル

表示名は「録音品質」ではなく「RVC学習適性」とする。 ユーザーが本当に知りたいのは「いい音か」ではなく「学習に向いてるか」。

┌─ RVC学習適性 ──────────────────────────────────┐
│                                                 │
│           87 / 100    A                         │
│                                                 │
│  ノイズレベル     ████████░░  良好              │
│  音量安定度       ███████░░░  普通              │
│  クリッピング     ██████████  問題なし          │
│  無音比率         █████████░  良好              │
│  子音明瞭度       ████████░░  良好   ← NEW      │
│  部屋反響         ███████░░░  普通   ← NEW      │
│                                                 │
│  💡 音量安定度を上げるにはマイクとの距離を       │
│     一定に保ってください                        │
└─────────────────────────────────────────────────┘

グレード定義

スコアグレード意味
90〜100S最高品質、即学習可
75〜89A良好、学習推奨
60〜74B普通、前処理で改善を
40〜59C要改善、再録音を検討
0〜39D学習非推奨、再録音推奨

スコア算出ロジック(6項目)

項目配点算出方法
ノイズレベル25点SNR(信号対雑音比)から換算
音量安定度20点RMS音量の分散から換算
クリッピング20点サンプル値が0.99以上の割合
無音比率15点無音区間が全体の20〜40%が理想
子音明瞭度10点4kHz〜8kHz帯域のエネルギー比率 ← NEW
部屋反響10点簡易RT60推定(decay rate)← NEW

新規スコア項目の詳細

子音明瞭度(10点)

RVCは母音より子音の変換が難しく、子音が潰れると機械感が出る。 s / t / k / sh などの高域成分(4kHz〜8kHz)のエネルギー比率を見る。

def calc_consonant_score(y, sr):
    # 4kHz〜8kHzのエネルギー比率
    stft = np.abs(librosa.stft(y))
    freqs = librosa.fft_frequencies(sr=sr)
    consonant_mask = (freqs >= 4000) & (freqs <= 8000)
    consonant_energy = stft[consonant_mask].mean()
    total_energy = stft.mean()
    ratio = consonant_energy / (total_energy + 1e-10)
    # 理想比率: 0.15〜0.35
    score = 10 if 0.15 <= ratio <= 0.35 else max(0, 10 - abs(ratio - 0.25) * 40)
    return int(score)

将来的なアドバイス例:

  • 「子音が潰れています → マイクとの距離を少し離してください」
  • 「高域が多すぎます → ハイカットを14kHzに下げてみてください」

部屋反響スコア(10点)

簡易RT60推定で残響時間を計測。残響が多いと学習データに部屋の音が混入する。

def calc_reverb_score(y, sr):
    # 簡易RT60推定: エネルギーの減衰率を見る
    energy = librosa.feature.rms(y=y)[0]
    decay_rate = np.polyfit(np.arange(len(energy)), np.log(energy + 1e-10), 1)[0]
    # decay_rateが急峻 = 残響少ない = 良い
    if decay_rate < -0.05:
        return 10   # デッド(理想)
    elif decay_rate < -0.02:
        return 7    # 普通
    else:
        return 3    # 反響あり

将来的なアドバイス例:

  • 「部屋の反響が多いです → 布団や毛布を壁際に置くと改善します」
  • 「クローゼットの中での録音が効果的です」

adviceシステム

現在は固定文、将来的に動的生成に拡張できる設計にしておく。

def get_advice(scores: dict) -> str | None:
    if scores["clipping"] < 15:
        return "音が割れています。マイクの音量を下げるか、距離を離してください"
    if scores["noise"] < 15:
        return "ノイズが多いです。エアコンや換気扇を止めて録音してください"
    if scores["stability"] < 12:
        return "音量が不安定です。マイクとの距離を一定に保ってください"
    if scores["reverb"] < 5:
        return "部屋の反響が多いです。布団を横に置くか、クローゼット内での録音を試してください"
    if scores["consonant"] < 5:
        return "子音が聞き取りにくいです。マイクに少し近づいて、はっきり発音してください"
    return None

将来的な拡張方向

  • フォルマント変動 → 「マイクに近づいたり離れたりしています」
  • 低域比率変化 → 「ポップノイズが検出されました(ポップガード推奨)」
  • 有声/無声比率 → 「話すペースが速すぎます」

Pythonバックエンド

依存ライブラリ

librosa       # 波形解析・特徴量抽出 (ISC License) ※重い、~150MB
scipy         # フィルター処理 (BSD)
noisereduce   # ノイズリダクション (MIT)
soundfile     # WAV読み書き (BSD)
numpy         # 数値演算 (BSD)

⚠ librosaは依存チェーンが重い。インストール時間に注意。

API

POST /audio/process
  body: {
    input_path: string,
    trim_silence: bool,           // default: true
    noise_reduce: float,          // 0〜1, default: 0.5 (0=無効)
    lowcut_hz: int,               // default: 80
    highcut_hz: int,              // default: 16000
    gain_mode: "auto" | "manual",
    gain_db: float                // -12〜+12, default: 0
  }
  response: {
    output_path: string,
    score: QualityScore
  }

POST /audio/score
  body: { input_path: string }
  response: QualityScore

POST /audio/env-check
  body: { wav_base64: string }    // 3秒の環境音WAV
  response: {
    noise_level_db: float,
    status: "quiet" | "noisy" | "loud"
  }

型定義

interface QualityScore {
  total: number                                           // 0〜100
  grade: "S" | "A" | "B" | "C" | "D"
  noise: number                                          // 0〜25
  stability: number                                      // 0〜20
  clipping: number                                       // 0〜20
  silence_ratio: number                                  // 0〜15
  consonant: number                                      // 0〜10 (NEW)
  reverb: number                                         // 0〜10 (NEW)
  advice?: string
}

デフォルト値まとめ

パラメーターデフォルト推奨範囲備考
無音トリミングON常時推奨
ノイズリダクション0.50.3〜0.7強すぎると声質劣化
ローカット80Hz60〜200Hzファン・エアコン除去
ハイカット16000Hz12k〜20kHz高周波ノイズ除去
ゲインモードオートピーク -3dBFS

新規・変更ファイル

ファイル種別内容
python/routers/audio_process.py新規3エンドポイント + 6項目スコア算出
python/server.py変更audio_process router追加
src/pages/AudioQualityPage.tsx新規音声前処理メインページ
src/components/WaveformMeter.tsx新規リアルタイム波形 + 音量バー(canvas)
src/components/QualityScorePanel.tsx新規RVC学習適性スコア表示(6項目)
src/lib/api.ts変更QualityScore型 + 3 APIメソッド追加
src/App.tsx変更AudioQualityPageルーティング追加
src/components/layout/Sidebar.tsx変更「音声前処理」ナビ追加(声質変換の次)

完了条件

  • リアルタイム波形・音量メーター(Web Audio API + canvas)
  • 波形カラーリング(緑/黄/赤)
  • 録音前環境音チェック(3秒計測)
  • 無音トリミング
  • ノイズリダクション(強度スライダー)
  • ローカット / ハイカットフィルター
  • ゲイン調整(オート / 手動)
  • RVC学習適性スコア表示(6項目 + グレード + アドバイス)
  • 子音明瞭度スコア
  • 部屋反響スコア
  • 処理前後の試聴比較

将来フェーズ(Phase 4以降)

  • adviceの動的生成(フォルマント変動・ポップノイズ検出)
  • 録音距離安定度(RMS + 低域比率 + 音量揺れの複合判定)
  • 「録音が上手くなる」フィードバックループ設計