Skip to content

口型动作同步

318 words
2 min

口型动作同步功能需要模型仅支持 motionsync3, 在使用此功能之前, 请检查模型是否存在 motionsync3.json 文件. 或者你还可以使用 live2d 官方为演示口型同步所提供的示例模型: kei_vowels_pro

使用AudioBuffer

可以将 AudioBuffer 作为参数, 之后调用 speak 方法, 就可以实现模型的口型动作同步, 你可以借助一个tts服务将一段文本转为 AudioBuffer.

在调用说话方法之前,需要先手动加载该模型的 motionsync3 文件:

ts
model.loadMotionSyncFromUrl('https://model.hacxy.cn/kei_vowels_pro/kei_vowels_pro.motionsync3.json');

在这个例子中, 点击说话按钮, 让该模型说出输入框的内容

示例代码:

ts
async function tts(text: string) {
  const response = await fetch('https://tts.hacxy.cn/tts', {
    method: 'POST',
    body: JSON.stringify({
      voice: 'zh-CN-XiaoxiaoNeural',
      text,
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  }).then(res => res.arrayBuffer());
  // 创建 AudioContext 实例
  const audioContext = new AudioContext();
  // 使用 decodeAudioData 解码 ArrayBuffer
  const audioBuffer = await audioContext.decodeAudioData(response);
  return audioBuffer;
}

const main = async () => {
  const inputEl = document.createElement('input');
  inputEl.style.backgroundColor = '#fff';
  const buttonEl = document.createElement('button');
  buttonEl.className = 'say-button';
  buttonEl.innerHTML = '说话';
  inputEl.className = 'say-input';
  inputEl.value = '这是一段文字, 用于测试口型动作同步';
  canvasEl.parentElement?.append(inputEl, buttonEl);

  const model = await l2d.create({
    path: 'https://model.hacxy.cn/kei_vowels_pro/kei_vowels_pro.model3.json',
    scale: 0.3
  });

  model.loadMotionFromUrl('https://model.hacxy.cn/kei_vowels_pro/kei_vowels_pro.motionsync3.json');

  buttonEl.addEventListener('click', async () => {
    const audioBuffer = await tts(inputEl.value);
    model.speak(audioBuffer);
  });

  return model;
};
main();

使用媒体流

在下面这个例子中, 通过调用麦克风权限, 并通过人声来播放口型动作同步

ts
const model = await l2d.create({
  path: 'https://model.hacxy.cn/kei_vowels_pro/kei_vowels_pro.model3.json',
  scale: 0.3
});

model.loadMotionStreamFromUrl('https://model.hacxy.cn/kei_vowels_pro/kei_vowels_pro.motionsync3.json');

const mediaStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
});

model.speakStream(mediaStream);

buttonEl.addEventListener('click', async () => {
  mediaStream.getTracks().forEach(track => track.stop());
  model.resetSpeakStream(); // 重置口型动作
});

TIP

点击运行时, 将在你的浏览器中申请麦克风权限, 如果申请得到允许, 你可以尝试对麦克风说些什么, 点击停止说话, 将会关闭麦克风权限, 同时重置口型动作

MIT Licensed