4. 声・表情・安全制御・運用設定
4.1 文章が演技になるまで
flowchart LR
A[LLMの本文と補助タグ] --> B[ResponseParser]
B --> C[CleanText: 字幕・履歴]
B --> D[TtsText: 感情・音響指示を保持]
D --> E[TTS: 分割・合成・先読み]
E --> F[AudioSource実再生]
E --> G[話者別の表情と口パク]
F --> H[配送結果と監査]
ResponseParser は本文と、感情・思考・キャラ間interaction・視聴者メモ・コントローラー指示等を分ける。字幕用の CleanText と、音声演出タグを残す TtsText は別。Irodori用スタイル絵文字やASMRタグも、字幕・記憶からは除き、対応する音声経路へ渡す。
感情は、LLMが適切なタグを出せばそれを採用する。タグが無ければ EmotionManager.AnalyzeEmotion の経路へ進む場合がある。タグ数が多いことと、聞き取りやすく自然な演技であることは同義ではない。
4.2 TTSの実装範囲
TTSController のエンジン種別は、Voicevox / Azure / BertVits2 / ElevenLabs / Chatterbox / ChatTTS / PiperPlus / Irodori / Qwen3TTS / AivisCloud。列挙されていることは、各環境でサービスが起動・認証・設定済みであることを意味しない。
| 仕組み | 確認した実装 | 評価時の注意 |
|---|---|---|
| 発話の直列化 | semaphore、取消、requestGate | キュー処理と別に音声待ちがある |
| 文・感情ごとのチャンク | Chunking | LLM全文生成後の処理。LLMトークンの逐次読み上げではない |
| 次チャンクの先読み | 再生と次の合成を重ねる | 先頭音声の合成待ちは残る |
| 発話単位の設定固定 | 論理発話中のTTS/声/感情設定変更を遅延 | 設定同期で途中から声が変わる事故を抑える |
| 一時的な声の指定 | VoiceOverride にキャラID、エンジン、話者・参照音声等 |
ゲストの一時指定とホスト設定の保存を区別 |
| 読み補正 | TTS辞書、provider別の文字処理 | 表示本文と音声providerへ送る本文が異なる場合がある |
| 配送追跡 | SpeechPlaybackResult |
完了、可聴の有無、実配送本文を別々に返す |
AivisCloudの例外: 現作業ツリーの useChunks はAivisCloudを除外する。呼び出し回数を抑えるため一つの合成へまとめるので、他のエンジンと同じチャンク単位の感情切替・間になるとは限らない。
SpeechPlaybackResult.Completed=true でも重複抑止等で Played=false になり得る。逆に途中で失敗した場合、Completed=false でも先頭部分の DeliveredText が残り得る。返答件数や台本進捗を「Taskが成功した数」だけで数えると、視聴者が聞いた体験とずれる。
音声側にも再試行・circuit breaker・semaphore復旧がある。停止しにくさのための設計だが、復旧中の間や代替声の違いまで品質が保証されるわけではない。
4.3 声の感情とアバターの感情
EmotionVoiceParameter は、速度・ピッチ・抑揚・音量・前後の無音・VOICEVOXスタイル切替を表す。EmotionVoiceConfig は感情と強度から値を作る。
TTScontroller.VoiceEffects.ApplyEmotionParameterToManager はproviderごとに分岐する。このswitchにはPiperPlusとAivisCloudの同じ感情設定呼び出しがない。別の音声修飾経路はあるため「両者は一切感情表現できない」とは断定しないが、全エンジンが同等にタグを演技へ変換すると仮定してはいけない。
ICharacterAvatar は SetEmotion / SetNeutral / TriggerSpeaking / SetMoodBaseline を提供する。Live2D / VRM / PSDの実装がある。TTSは話者を固定したleaseで表情・発話開始/終了を扱い、口が開いたまま残ることや、キャラ切替後に別のアバターへ終了通知することを防ぐ。
ただしinterfaceの一部は未対応実装ならno-opを許す。AnimationBridge の感情→動作マッピングにも集約がある。したがって以下は別々に確認する必要がある。
- 生成文が意図する感情。
- 音声providerが表現した抑揚・強さ・間。
- 現在ロードしたモデルに存在する表情・モーション。
- 実際の発話タイミングと口・表情の同期。
ActivityStateCoordinator にはIdle / Listening / Thinking / Speaking / Sleepingがある。「考えている」「聞いている」も表現対象だが、実機の視線や姿勢が自然に伝わるかは映像確認が必要。
4.4 瞬間感情だけでなく持続状態もある
| 層 | 主な実装 | 役割 |
|---|---|---|
| 今回の感情 | AffectiveStateController | コメントや生成結果を受けた感情・強度 |
| 持続ムード | MoodEngine | 快/不快と覚醒度を蓄積・減衰させる |
| 感情の余力と余韻 | EmotionStateManager | 感情容量、残留、未解決状態、回復、永続化 |
| 話し方への修飾 | HumanLikenessManager | ためらい、気分、曖昧な記憶、話題の脱線、好み、相槌/無視の選択 |
| 既存機能の統合 | HumanLikeSpeechSystem | 配信フェーズ・間・自己認識・質問・関係等の参照と有効化 |
名前の似た HumanLikenessManager と HumanLikeSpeechSystem は別クラス。前者の生成後処理と、後者の各コンポーネントの存在を混同しない。通常LLM経路で実際に呼ばれる処理、プロンプトとしてのみ使う処理、配置だけの機能を分けて読む必要がある。
持続状態があるため、毎回答でneutralからhappyへ切り替えるだけのシステムではない。一方、ムードの蓄積が視聴者に理解できる理由・物語として表現されるか、嫌なコメントで配信全体の空気が沈み続けないかは、時間をかけた評価対象となる。
4.5 「間」と身体動作はどこまで実行されるか
PauseMarkerProcessor は [PAUSE:0.5] やTHINKING / EMOTIONAL / DRAMATIC等を解釈し、既定0.2–2.0秒の無音チャンクを作る。三点リーダー等も対象。SilenceManager は文脈に応じた間の挿入を担う。
これは間を表す機能がない状態ではない。ただし、ツッコミ直前の溜め、笑い終わり、視聴者が反応する余白を、配信の反応を見て継続調整する共通演出タイムラインまで確認できたわけではない。チャンク経路・provider・字幕先行の差も残る。
PhysicalActionManager は飲む・身だしなみ・姿勢・小物等の文字表現を生成・挿入・除去できる。今回の Assets/Scripts 内の呼び出し探索では InsertActionIntoResponse と GetActionPromptGuidance の通常応答からの呼び出しを確認できなかった。 HumanLikeSpeechSystem.ProcessResponse にも物理アクションの挿入はない。したがって、設定欄やクラスの存在だけで「水を飲む動作を映像として実行する」と評価しない。UnityEvent等のシリアライズ配線や外部呼び出しは別途未確認。
4.6 安全制御と配信継続
| 層 | 実装 | 応答への影響 |
|---|---|---|
| 入力/出力の安全 | ContentFilterManager、ChatGPTController.Safety | NG、保護情報、禁止ユーザー、誘導等。通常返答を代替文へ変える場合がある |
| タグ副作用の境界 | ChatGPTController、ResponseParser | 本文が安全処理・長さ制限で変わったら元タグの副作用を抑える |
| 発話ループ | SpeechLoopDetector | 類似発話、発話頻度、同一ノード反復を検知 |
| 緊急停止 | TTS / 運営カンペ / BroadcastCommandSyncManager | 生成取消・再生停止・後着発話の抑制 |
| 無音監視 | SilenceWatchdog | コード既定15秒で短いつなぎ、60秒でエスカレーション。最大連続3回 |
| 全provider失敗 | OfflineFallbackResponder | 5分内2回の失敗で発動、180秒の障害窓、30–60秒間隔の定型雑談/名前呼び |
| キャラ逸脱の観測 | CharacterConsistency | 実発話後にNG表現・語尾等を確認。全発話の事前修正器ではない |
SpeechLoopDetectorの既定は直近5発話・類似度0.8・類似3件、100文字以上では類似度0.95の2件を追加検知する。さらに60秒内10発話超や、同一ノード通過も監視する。安全のための反復防止と、視聴者が喜ぶ「お約束」の反復を区別できるかは体験上の論点になる。
無音監視は睡眠や実TTS再生中などを考慮する。15秒という値を、すべての配信状態で必ず15秒後にフィラーが鳴る保証として読まない。障害中の定型発話は沈黙回避として有用だが、その場に合う話題を生む通常の企画・雑談とは異なる。
キャラ逸脱検知は、文字列のNGや語尾に基づく限定的な指標。価値観の矛盾、前回と逆の好み、設定にない体験の捏造、気持ちの自然な変化までを判定する意味評価ではない。
4.7 設定を変えても効かない場合の確認順
flowchart LR
A[Adminフォーム] --> B[Functionsの検証・保存]
B --> C[キャラ設定同期]
C --> D[実行中コンポーネントに適用]
D --> E[今回の経路・ゲート・予算]
E --> F[LLM / TTS / モデルの表現能力]
根拠は Admin設定UI、Functionsの設定検証、CharacterConfigSyncManager.ApplyCloudConfigToLocal。
CharacterConfigSyncManager は人格周辺、TTS、声辞書、感情、記憶、PII公開、会話長、LLM、HumanLikeness、質問、コラボ、アバター等へ個別に適用する。対応コンポーネントを FindObjectOfType 等で解決できないと適用できず、警告で終わる経路もある。
| 確認対象 | 主な設定・実装 | 意味 |
|---|---|---|
| 通常応答 | ChatGPTConfig、LLMcontroller.RemoteConfig | ON/OFF、モデル、文字数、会話品質v1/v2 |
| 自発発話 | Monologue設定、台本状態、ASMR/ゲーム/展示/コラボ | 主スイッチだけで全場面に発話するわけではない |
| 個人への記憶 | viewerPiiPromptPolicyConfig | 保存・公開許可・今回の注入量を分離 |
| キャラの体験 | characterExperienceConfig | 目標、ためらい、判断軸、配信横断等 |
| 台本参加 | 各ノードのaudienceInteraction等 | 全体ONでも現在ノードが無効なら動かない |
| 演技 | ttsConfig / emotionVoiceConfig / アバター資産 | テキストの指示と実音声・映像を一致させる |
コードのフィールド初期値、Unityのシリアライズ値、クラウドからの同期値、発話中の固定値は異なる場合がある。本資料は前者と適用ロジックを分析したもので、各キャラの実効値一覧ではない。
4.8 何が観測でき、何がまだ測れていないか
SpeechAuditReporter は実再生した本文とフィルター発動内容を専用監査へ送る。永続キューと再送時のeventId維持があり、通常clientLogsとは別。ライセンス・送信成功・キュー上限等の条件があるため、ログ収集そのものの欠落も考慮する。
BroadcastHealthReporter と台本の ScriptInteractionMetrics で、稼働状態、質問の受付/開始/配送、寄り道等を観測できる。キャラ逸脱、応答長診断、PII注入診断もある。
これらは「出力が生成できた」「本当に発話した」「どこで止まった」の分析を支える。一方、笑えた、続きが気になった、初見が参加しやすかった、キャラを好きになった、という評価は直接得られない。コメント増加や課金は代理指標であり、面白さそのもののラベルではない。