更新记录

1.0.0(2026-05-10)

  • 支持 App Android 和 App iOS 原生 Live2D 模型渲染。
  • 支持模型加载、动作播放、表情切换、参数控制、触摸命中。
  • 支持语音播放、WAV/音频口型驱动、动作自带声音。
  • 支持 AI 实时 PCM16 音频流播放和口型同步。

平台兼容性

uni-app x(5.08)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × × ×

em-live2d 插件使用文档

em-live2d 是 uni-app UTS 原生组件插件,用于在 App 端渲染 Live2D Cubism 模型。插件支持 Android 和 iOS,可在 nvue/uvue 页面中加载模型、播放动作、切换表情、控制参数、播放语音、驱动口型,并接入 AI 实时语音输出。

支持范围

平台 支持
App Android 支持
App iOS 支持
Web/H5 不支持原生 Live2D 渲染
小程序 不支持原生 Live2D 渲染

应用场景

em-live2d 适合需要在 App 内嵌入可交互虚拟角色的场景:

场景 说明
AI 虚拟助手 结合语音识别、实时大模型和 TTS,让 Live2D 角色完成问答、提醒、讲解和陪伴
实时语音对话 AI 返回 PCM 音频流时,边播边驱动口型,适合低延迟对话体验
语义驱动角色 根据意图、情绪、语气切换表情、动作、视线和身体参数,让角色不只是“说话动嘴”
数字人客服 在咨询、导购、售后等流程中用虚拟角色承载服务入口
教学和导览 用角色讲解课程、流程、产品、景点或业务规则
陪伴和互动角色 做桌面宠物、情绪陪伴、互动头像、角色扮演等 App 功能
活动和营销页 在 App 内使用品牌虚拟形象做互动展示、欢迎语、动作表演
本地模型演示 快速验证 Live2D 模型资源、动作、表情、音频和口型效果

资源放置

建议将 Live2D 模型资源放到应用的 static/live2d 目录:

static/live2d/
  165 204/
    165 204.model3.json
    165 204.moc3
    165 204.physics3.json
    165 204.4096/
      texture_00.png
    motion/
      idle.motion3.json
      dance.motion3.json
    expressions/
      smile.exp3.json
    sounds/
      song.wav

页面中使用 /static/... 路径:

/static/live2d/165 204/165 204.model3.json
/static/live2d/165 204/sounds/song.wav

如果模型是下载到本地的,也可以传绝对本地文件路径。路径必须指向 .model3.json

基础用法

<template>
  <view class="page">
    <em-live2d
      ref="avatar"
      class="avatar"
      model="/static/live2d/165 204/165 204.model3.json"
      :autoIdle="true"
      :enableMotionSound="true"
      :voiceVolume="1"
      @modelLoaded="onModelLoaded"
      @modelLoadFailed="onModelLoadFailed"
      @motionFinished="onMotionFinished"
      @voiceEnded="onVoiceEnded"
      @nativeError="onNativeError"
    />
  </view>
</template>

<script>
export default {
  methods: {
    onModelLoaded(event) {
      console.log('Live2D model loaded', event)
    },
    onModelLoadFailed(error) {
      console.log('Live2D model load failed', error)
    },
    onMotionFinished(event) {
      console.log('Live2D motion finished', event)
    },
    onVoiceEnded(event) {
      console.log('Live2D voice ended', event)
    },
    onNativeError(error) {
      console.log('Live2D native error', error)
    }
  }
}
</script>

<style>
.page {
  flex: 1;
}

.avatar {
  width: 750rpx;
  height: 980rpx;
}
</style>

Props

Prop 类型 默认值 说明
model String '' .model3.json 路径,推荐 /static/...
autoIdle Boolean true 模型加载后自动播放 Idle 随机动作
enableMotionSound Boolean true 动作配置里包含 Sound 时自动播放对应声音
voiceVolume Number 1.0 语音播放音量

加载模型

通过 model 属性加载:

<em-live2d ref="avatar" model="/static/live2d/165 204/165 204.model3.json" />

也可以手动加载:

this.$refs.avatar.loadModel('/static/live2d/165 204/165 204.model3.json')

模型加载成功会触发 modelLoaded,失败会触发 modelLoadFailed

动作

动作必须在 .model3.jsonFileReferences.Motions 中声明。调用时使用动作组名和索引:

this.$refs.avatar.startMotion('Dance', 0, 3)
this.$refs.avatar.startRandomMotion('Idle', 1)
this.$refs.avatar.stopAllMotions()

优先级建议:

优先级 用途
1 待机、倾听、低优先级动作
2 普通动作
3 用户主动触发、强制打断当前动作

如果动作没有播放,先确认:

  • .model3.json 中存在该 motion group。
  • index 没有越界。
  • motion 文件路径正确并已打包。
  • 当前动作优先级没有被更高优先级动作占用。

表情和参数

表情必须在 .model3.jsonExpressions 中声明:

this.$refs.avatar.setExpression('smile')
this.$refs.avatar.setRandomExpression()

参数控制:

this.$refs.avatar.setParameter('ParamAngleX', 15)
this.$refs.avatar.addParameter('ParamAngleY', 5, 1)
this.$refs.avatar.multiplyParameter('ParamEyeLOpen', 0.8, 1)
this.$refs.avatar.setParametersBatch(['ParamAngleX', 'ParamAngleY'], [10, -5])

const value = this.$refs.avatar.getParameter('ParamAngleX')

只有模型 .moc3 中真实存在的参数才会生效。

语音和口型

手动控制口型

this.$refs.avatar.setLipSyncValue(1)
this.$refs.avatar.setLipSyncValue(0)
this.$refs.avatar.setLipSyncValues([0.2, 0.8, 0.1])

播放音频并驱动口型

this.$refs.avatar.startLipSyncFromWav('/static/live2d/165 204/sounds/song.wav')
this.$refs.avatar.startLipSyncFromAudio('/static/live2d/165 204/sounds/song.wav')
this.$refs.avatar.stopLipSync()

startLipSyncFromWav(path) 会播放 WAV 并根据音频 RMS 驱动嘴部。startLipSyncFromAudio(path) 用当前平台音频能力播放并驱动口型。

只播放语音

this.$refs.avatar.playVoice('/static/live2d/165 204/sounds/song.wav', false)
this.$refs.avatar.stopVoice()

播放语音并驱动口型

this.$refs.avatar.playVoice('/static/live2d/165 204/sounds/song.wav', true)

语音相关事件:

<em-live2d
  @voiceStarted="onVoiceStarted"
  @voiceEnded="onVoiceEnded"
  @voiceError="onVoiceError"
/>

动作自带声音

如果 motion 条目包含 Sound,并且组件 enableMotionSoundtrue,播放该动作时会自动播放声音:

{
  "File": "motions/touch_01.motion3.json",
  "Sound": "sounds/haru_talk_13.wav"
}

Sound 路径相对于当前模型目录。

AI 实时语音输出

插件只负责 AI 语音输出的播放和口型驱动;用户麦克风采集、WebSocket、AI 协议由业务层或其他插件处理。

AI 服务返回 PCM16 音频流时,按下面流程推给 Live2D:

this.$refs.avatar.startRealtimeVoice(24000, 1, 'pcm16')
this.$refs.avatar.pushAudioChunk(base64Pcm16Chunk)
this.$refs.avatar.stopRealtimeVoice()

实时音频要求:

要求
编码 signed 16-bit little-endian PCM
声道 mono 或 stereo
采样率 调用 startRealtimeVoice(sampleRate, channels, 'pcm16') 时传入
chunk pushAudioChunk() 参数为 base64 PCM 数据

如果 AI 服务已经计算好音量或口型权重,可以直接驱动:

this.$refs.avatar.pushAudioLevel(0.65)
this.$refs.avatar.pushViseme('ParamMouthOpenY', 0.65)

触摸、拖拽和命中区域

this.$refs.avatar.setDrag(x, y)
this.$refs.avatar.tap(x, y)

命中区域通过 hitArea 事件返回:

<em-live2d @hitArea="onHitArea" />
onHitArea(event) {
  console.log('hit area', event.message)
}

获取模型信息

getModelInfo() 返回 JSON 字符串,可用于查看当前模型的动作组、表情、参数和命中区域:

const raw = this.$refs.avatar.getModelInfo()
const info = JSON.parse(raw)
console.log(info)

停止和释放

常见停止逻辑:

this.$refs.avatar.stopRealtimeVoice()
this.$refs.avatar.stopVoice()
this.$refs.avatar.stopLipSync()
this.$refs.avatar.stopAllMotions()
this.$refs.avatar.startRandomMotion('Idle', 1)

页面销毁时通常组件会跟随页面释放。需要主动释放时:

this.$refs.avatar.releaseLive2D()

方法总表

方法 说明
loadModel(path) 加载 .model3.json
startMotion(group, index, priority = 2) 播放指定动作
startRandomMotion(group, priority = 2) 随机播放动作组
stopAllMotions() 停止全部动作
setExpression(name) 设置表情
setRandomExpression() 随机表情
setParameter(id, value) 设置参数
addParameter(id, value, weight = 1) 叠加参数
multiplyParameter(id, value, weight = 1) 乘法调整参数
setParametersBatch(ids, values) 批量设置参数
getParameter(id) 获取参数值
setLipSyncValue(value) 设置口型值
setLipSyncValues(values) 设置一组口型值,目前取最后一个
startLipSyncFromWav(path) 播放 WAV 并驱动口型
startLipSyncFromAudio(path) 播放音频并驱动口型
stopLipSync() 停止口型驱动
playVoice(path, driveLipSync = false) 播放语音,可选驱动口型
stopVoice() 停止语音
startRealtimeVoice(sampleRate = 24000, channels = 1, format = 'pcm16') 开始实时 PCM16 语音播放
pushAudioChunk(base64Chunk) 推入 base64 PCM16 音频 chunk
pushAudioLevel(rms) 直接推入音量值驱动口型
pushViseme(id, weight) 直接推入口型或参数权重
stopRealtimeVoice() 停止实时语音播放
setDrag(x, y) 设置拖拽坐标
tap(x, y) 触发点击检测
getModelInfo() 返回模型信息 JSON 字符串
releaseLive2D() 释放原生资源

事件总表

事件 说明
modelLoaded 模型加载成功
modelLoadFailed 模型加载失败
motionStarted 动作开始
motionFinished 动作结束
expressionChanged 表情变化
hitArea 点击命中区域
voiceStarted 语音开始
voiceEnded 语音结束
voiceError 语音失败
lipSyncStarted 口型驱动开始
lipSyncEnded 口型驱动结束
nativeError 原生错误

事件 payload 通常包含:

{
  type: 'motionFinished',
  code: null,
  message: 'Dance'
}

不同事件的 message 可能是模型路径、动作组、音频路径、命中区域或错误描述。

常见问题

模型加载失败

检查:

  • model 是否指向 .model3.json
  • /static/... 路径和真实文件名是否完全一致。
  • .model3.json 引用的 .moc3、贴图、动作、表情文件是否存在。
  • 模型目录或文件名有空格时,传入路径也必须完全一致。

动作无法播放

常见原因:

  • .model3.json 没有对应 motion group。
  • index 越界。
  • motion 文件路径错误。
  • 当前动作优先级更高。

可尝试:

this.$refs.avatar.stopAllMotions()
this.$refs.avatar.startMotion('Dance', 0, 3)

动作开始了但模型不动

动作文件里的参数 ID 必须存在于模型 .moc3。如果 motion 修改的是模型不存在的参数,动作会被播放,但视觉上不会变化。

嘴不动

检查 .model3.json 是否存在 Groups -> LipSync,并且包含当前模型实际嘴部参数,常见参数是 ParamMouthOpenY

没声音

检查:

  • 音频路径是否正确。
  • voiceVolume 是否大于 0
  • 是否收到 voiceError
  • 当前平台是否支持该音频格式。
  • 实时流是否为 PCM16 little-endian。

调试日志

Android 模型、动作、音频加载问题:

adb logcat -c
adb logcat -v time | grep -E "HylLive2D|NativePrint|model|moc|texture|motion|Live2D"

Android 崩溃和原生错误:

adb logcat -c
adb logcat -v time | grep -E "AndroidRuntime|FATAL|SIGSEGV|NativePrint|Live2D|HylLive2D|em_live2d"

iOS 可在 Xcode 的 Devices and Simulators -> Open Console 或 macOS Console 中按进程名、Bundle ID、EmLive2DNativePrint 过滤日志。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

件不采集任何数据

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。