Lip-sync Based on Volume of Wav Files (Web)

Updated: 05/13/2021

Summary

The Cubism SDK for Web sample uses the lip-sync function to provide real-time lip-sync movement based on the volume of the audio data in the wav file.
This sample is provided with the Cubism 4 SDK for Web R3 beta1 or later.

How to Use

Preparation

Describe the wav file associated with the motion in the .json file. Specify the wav file path corresponding to the “Sound” key for each motion.

{
	・
	・
	・
		"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"}
			]
		},
	・
	・
	・
}

Place the wav file in the location specified above; if the path to the wav file is incorrect, lip-sync will not be performed.

Start of volume acquisition

In the sample, information is acquired from a wav file via the LAppWavFileHandler class.
Executing LAppWavFileHandler::Start() reads audio data from a wav file and initializes the internal state necessary to perform lip-sync.

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);
    }
    ・
    ・
    ・ 
}

Status update and volume acquisition

LAppWavFileHandler::Update() is executed to measure the volume of the part corresponding to the elapsed time. The volume of the measurement results can be obtained with LAppWavFileHandler::GetRms(). Set the obtained volume as a lip-sync value for the model with the CubismModel::AddParameterValue function.

In the sample, the acquired volume is multiplied by 0.8 to obtain the lip-sync value. Here, it is also possible to set the lip-sync value to a volume obtained from a sound library or other source.

public update(): void {
    ・
    ・
    ・
    // Lip-sync settings
    if (this._lipsync) {
      let value = 0.0; // For real-time lip-sync, get the volume from the system and enter a value in the range between 0 and 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);
      }
    }
    ・
    ・
    ・
}

Additional information

  • The sample does not have the ability to play audio on the device.
  • LAppWavFileHandler::GetRms() returns the current volume value in the range between 0 and 1.
    • The unit for volume is RMS (root mean square).
    • Calculates the average of all channel audio.
      • For example, in the case of stereo audio, the average value of the audio including the left and right channels is calculated.

Restrictions

The sample supports loading the following wav files. Lip-sync will not be performed if a file that is not in one of the supported formats is loaded.

  • Microsoft WAV (Little Endian format)
  • Linear PCM
    • Wav files encoded in μ-raw, ADPCM, etc. are not supported.
  • Number of channels: Mono/Stereo
  • Supported bit depths: 8, 16, 24-bit signed integer
Please let us know what you think about this article.