wavファイルの音量に基づくリップシンク(Web)

最終更新: 2021年5月13日

概要

Cubism SDK for Webサンプルでは、リップシンク 機能を使用し、wavファイルの音声データの音量を基にリアルタイムにリップシンクを動かす機能を提供しています。
このサンプルは Cubism 4 SDK for Web R3 beta1 以降で提供しています。

使用方法

準備

モーションに紐づいたwavファイルを .json ファイルに記述します。各モーションの “Sound” キーに対応するwavファイルパスを指定してください。

{
	・
	・
	・
		"Motions": {
			"Idle": [
			  {"File":"motions/haru_g_idle.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_05.wav"},
			  {"File":"motions/haru_g_m15.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_06.wav"}
			],
			"TapBody": [
			  {"File":"motions/haru_g_m06.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_01.wav"},
			  {"File":"motions/haru_g_m09.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_02.wav"},
			  {"File":"motions/haru_g_m20.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_03.wav"},
			  {"File":"motions/haru_g_m26.motion3.json" ,"FadeInTime":0.5, "FadeOutTime":0.5, "Sound": "sounds/haru_normal_04.wav"}
			]
		},
	・
	・
	・
}

上記で指定した場所にwavファイルを配置してください。wavファイルのパスが間違っているとリップシンクは行われません。

音量取得開始

サンプルでは、LAppWavFileHandlerクラスを介してwavファイルからの情報取得を行っています。
LAppWavFileHandler::Start() を実行すると、wavファイルから音声データを読み込み、リップシンクを行うために必要な内部状態を初期化します。

public startMotion(
  group: string,
  no: number,
  priority: number,
  onFinishedMotionHandler?: FinishedMotionCallback
): CubismMotionQueueEntryHandle {
    ・
    ・
    ・
    //voice
    const voice = this._modelSetting.getMotionSoundFileName(group, no);
    if (voice.localeCompare('') != 0) {
      let path = voice;
      path = this._modelHomeDir + path;
      this._wavFileHandler.start(path);
    }
    ・
    ・
    ・ 
}

状態更新と音量の取得

LAppWavFileHandler::Update() を実行すると、経過時間に対応した部分の音量の計測が行われます。計測結果の音量は LAppWavFileHandler::GetRms() で取得できます。取得した音量をリップシンク値として、モデルに CubismModel::AddParameterValue 関数で設定します。

サンプルでは、取得してきた音量を0.8倍してリップシンク値としています。ここで、サウンドライブラリ等から取得した音量をリップシンク値に設定することも可能です。

public update(): void {
    ・
    ・
    ・
    // リップシンクの設定
    if (this._lipsync) {
      let value = 0.0; // リアルタイムでリップシンクを行う場合、システムから音量を取得して、0~1の範囲で値を入力します。

      this._wavFileHandler.update(deltaTimeSeconds);
      value = this._wavFileHandler.getRms();

      for (let i = 0; i < this._lipSyncIds.getSize(); ++i) {
        this._model.addParameterValueById(this._lipSyncIds.at(i), value, 0.8);
      }
    }
    ・
    ・
    ・
}

補足

  • サンプルには音声をデバイス上で再生させる機能はありません。
  • LAppWavFileHandler::GetRms() は現在の音量値を0~1の範囲で返します。
    • 音量の単位はRMS(二乗平均平方根)です。
    • 全チャンネル音声の平均値を計算します。
      • 例えばステレオ音声の場合、左右チャンネルを含めた音声の平均値を計算します。

制限事項

サンプルでは、以下のwavファイルの読み込みに対応しています。下記フォーマットに対応していないファイルを読み込ませた場合、リップシンクが行われません。

  • Microsoft WAV (リトルエンディアン形式)
  • リニアPCM
    • μ-raw、ADPCM等にエンコードされたwavは未対応です。
  • チャンネル数: モノラル/ステレオ
  • 対応ビット深度: 8, 16, 24bit符号付き整数
この記事に関するご意見・
ご要望をお聞かせください。