Project Icon

uLipSync

Unity口型同步资产 支持实时分析和预烘焙处理

uLipSync是一款Unity口型同步资产,采用Job System和Burst Compiler技术提高性能。支持实时分析和预烘焙处理,可集成Timeline并转换为AnimationClip。系统支持角色配置文件创建、麦克风输入、VRM模型和WebGL。提供校准工具便于调整口型同步效果。

uLipSync

uLipSync是一款用于Unity的唇型同步资源。它具有以下特点:

  • 利用Job SystemBurst Compiler在任何操作系统上更快运行,无需使用原生插件。
  • 可以校准以创建每个角色的配置文件
  • 支持实时分析和预烘焙处理。
  • 预烘焙处理可以与Timeline集成。
  • 预烘焙数据可以转换为AnimationClip

功能特性

唇型同步

[图片]

配置文件

[图片]

实时分析

[图片]

麦克风输入

[图片]

预烘焙

[图片]

Timeline

[图片]

AnimationClip

[图片]

纹理变化

[图片]

VRM支持

[图片]

WebGL支持

[图片]

安装

  • Unity包
    • Release页面下载最新的.unitypackage。
    • 从Package Manager导入Unity.BurstUnity.Mathematics
  • Git URL (UPM)
    • 在Package Manager中添加https://github.com/hecomi/uLipSync.git#upm
  • Scoped Registry (UPM)
    • 在项目中添加一个作用域注册表。
      • URL: https://registry.npmjs.com
      • 作用域: com.hecomi
    • 在Package Manager中安装uLipSync。

使用方法

机制

AudioSource播放声音时,声音的缓冲会进入附加到同一GameObject的组件的OnAudioFilterRead()方法。我们可以修改这个缓冲来应用混响等音效,同时由于我们知道正在播放的波形类型,我们也可以分析它来计算梅尔频率倒谱系数(MFCC),这代表了人类声道的特征。换句话说,如果计算得当,当前播放的波形是"a"时,你可以得到听起来像"啊"的参数,当前波形是"e"时,你可以得到听起来像"诶"的参数(除了元音,像"s"这样的辅音也可以被分析)。通过将这些参数与预先注册的每个"aieou"音素的参数进行比较,我们可以计算每个音素与当前声音的相似度,并利用这些信息来调整SkinnedMeshRenderer的混合形状,实现准确的唇型同步。如果将麦克风输入馈送到AudioSource,你也可以对当前声音进行唇型同步。

执行这种分析的组件是uLipSync,包含音素参数的数据是Profile,移动混合形状的组件是uLipSyncBlendShape。我们还有一个uLipSyncMicrophone资源,用于播放麦克风的音频。以下是它的示意图。

[图片]

设置

让我们使用Unity娘进行设置。示例场景是Samples / 01. Play AudioClip / 01-1. Play Audio Clip。如果你是从UPM安装的,请导入Samples / 00. Common sample(包含Unity的资源)。

放置Unity娘后,在任何要播放声音的游戏对象上添加AudioSource组件,并设置一个AudioClip来播放Unity娘的声音。

[图片]

首先,在同一GameObject上添加uLipSync组件。现在,从列表中选择uLipSync-Profile-UnityChan并将其分配给组件的Profile槽(如果分配其他内容,例如Male,唇型同步将无法正常工作)。

[图片]

接下来,设置混合形状以接收分析结果并移动它们。将uLipSyncBlendShape添加到Unity娘的SkinnedMeshRenderer的根部。选择目标混合形状MTH_DEF,转到Blend Shapes > Phoneme - BlendShape Table,通过按+按钮添加7个项目:A、I、U、E、O、N和-("-"用于噪音)。然后如下图所示选择对应每个音素的混合形状。

[图片]

最后,要连接这两者,在uLipSync组件中,转到*Parameters > On Lip Sync Updated (LipSyncInfo)并按+添加一个事件,然后将带有uLipSyncBlendShape组件的游戏对象(或组件)拖放到写着None (Object)*的地方。在下拉列表中找到uLipSyncBlendShape,并在其中选择OnLipSyncUpdate

[图片]

现在运行游戏时,Unity娘说话时会移动她的嘴巴。

调整唇型同步

可以在uLipSyncBlendShape组件的Parameters中设置要识别的音量范围和嘴巴的响应速度。

[图片]

  • Volume Min/Max (Log10)
    • 设置要识别的最小和最大音量(闭合/最大开口)(对数10,所以0.1是-1,0.01是-2)。
  • Smoothness
    • 嘴巴的响应速度。

关于音量,你可以在uLipSync组件的Runtime Information中看到当前、最大和最小音量的信息,所以尝试根据这些信息进行设置。

AudioSource位置

在某些情况下,你可能想将AudioSource附加到嘴巴位置,而将uLipSync附加到另一个GameObject。在这种情况下,可能有点麻烦,但你可以在与AudioSource相同的GameObject上添加一个名为uLipSyncAudioSource的组件,并在uLipSync Parameters > Audio Source Proxy中设置它。Samples / 03. AudioSource Proxy是一个示例场景。

[图片]

麦克风

如果你想使用麦克风作为输入,在与uLipSync相同的GameObject上添加uLipSyncMicrophone。这个组件将生成一个以麦克风输入为片段的AudioSource。示例场景是Samples / 02-1. Mic Input

[图片]

Device中选择要用于输入的设备,如果勾选了Is Auto Start,它将自动启动。要启动和停止麦克风输入,在运行时按下如下所示UI中的Stop Mic / Start Mic按钮。

如果你想通过脚本控制,使用 uLipSync.MicUtil.GetDeviceList() 来识别要使用的麦克风,并将其 MicDevice.index 传递给该组件的 index。然后调用 StartRecord() 开始录音或 StopRecord() 停止录音。

请注意,麦克风输入在 Unity 中的回放会比你实际说话稍有延迟。如果你想使用其他软件捕获的声音进行广播,请在 uLipSync 组件中将 Parameters > Output Sound Gain 设置为 0。如果 AudioSource 的音量设置为 0,传递给 OnAudioFilterRead() 的数据将会静音,无法进行分析。

uLipSync 组件中,转到 Profile > Profile 并从列表中选择一个配置文件(男性选择 Male,女性选择 Female 等),然后运行它。但是,由于配置文件未经个性化,默认配置文件的准确性可能不太理想。接下来,我们将看看如何创建与你自己声音匹配的校准数据。

校准

到目前为止,我们使用了样本 Profile 数据,但在本节中,让我们看看如何为其他声音(配音演员的数据或你自己的声音)创建调整后的数据。

创建配置文件

uLipSync 组件中点击 Profile > Profile > Create 按钮将在 Assets 目录的根目录创建数据并将其设置到组件中。你也可以通过右键点击 Project 窗口 > uLipSync > Profile 来创建。

接下来,在 Profile > MFCC > MFCCs 中注册你想要识别的音素。基本上,AIUEO 就足够了,但建议添加一个表示呼吸的音素("-" 或其他适当的字符)以防止呼吸输入。只要你注册的字符与 uLipSyncBlendShape 匹配,你可以使用任何字母、平假名、片假名等。

接下来,我们将对我们创建的每个音素进行校准。

使用麦克风输入进行校准

第一种方法是使用麦克风。应该将 uLipSyncMicrophone 添加到对象中。校准将在运行时进行,所以启动游戏以分析输入。按住每个音素右侧的 Calib 按钮,同时对着麦克风发出每个音素的声音,例如 A 发 "AAAAA",I 发 "IIIIII",依此类推。如果是噪音,不要说话或对着麦克风吹气。

如果你预先设置了 uLipSyncBlendShape,观察嘴型如何逐渐匹配会很有趣。

如果你的说话方式略有不同,例如在自然声音和背景声音之间,你可以在 Profile 中注册多个相同名称的音素,并相应地进行调整。

使用 AudioClip 进行校准

下一种方法是使用音频数据进行校准。如果有一段说 "aaaaaaa" 或 "iiiiiii" 的声音,请循环播放并同样按下 Calib 按钮。然而,在大多数情况下,没有这样的音频,所以我们想通过剪辑现有音频中类似 "aaa" 或 "iii" 的部分并回放来实现校准。一个有用的组件是 uLipSyncCalibrationAudioPlayer。这是一个在稍微交叉淡入淡出你想播放的部分时循环音频波形的组件。

通过拖动边界选择似乎在说 "aaaaa" 的部分,然后为每个音素按下 Calib 按钮,将 MFCC 注册到 Profile 中。

校准技巧

进行校准时,应注意以下几点:

  • 在尽可能无噪音的环境中使用麦克风进行校准。
  • 确保注册的 MFCC 尽可能恒定。
  • 校准后,多次检查并重新校准不起作用的音素,或注册额外的音素。
    • 你可以注册多个相同名称的音素,所以如果改变声音音调时不匹配,尝试注册更多音素。
    • 如果音素不匹配,检查是否有错误的音素。
    • 如果 MFCC 中有同名但完全不同颜色模式的音素,可能是错误的(相同音素应该有相似的模式)。
  • 校准后检查时,折叠 Runtime Information
    • 编辑器每帧都会重绘,所以帧率可能会降到 60 以下。

预烘焙

到目前为止,我们已经看了运行时处理。现在我们将看看通过预计算生成数据。

机制

如果你有音频数据,你可以预先计算每帧将收到什么样的分析结果,所以我们将把它烘焙到一个名为 BakedDataScriptableObject 中。在运行时,我们将使用名为 uLipSyncBakedDataPlayer 的组件来播放数据,而不是使用 uLipSync 在运行时分析数据。这个组件可以像 uLipSync 一样通过事件通知分析结果,所以你可以注册 uLipSyncBlendShape 来实现唇形同步。这个流程如下图所示。

设置

示例场景是 Samples / 05. Bake。你可以通过 Project 窗口的 Create > uLipSync > BakedData 创建一个 BakedData

在这里,指定校准过的 Profile 和一个 AudioClip,然后点击 Bake 按钮来分析数据并完成数据生成。

如果一切正常,数据将如下所示。

将这些数据设置到 uLipSyncBakedDataPlayer 中。

现在你已经准备好播放了。如果你想在编辑器中再次检查,按下 Play 按钮,或者如果你想从另一个脚本播放,只需调用 Play()

参数

通过调整 Time Offset 滑块,你可以修改唇形同步的时机。在运行时分析中,无法在声音之前调整嘴巴的张开,但通过预计算,可以让嘴巴稍早打开,因此可以调整得更自然。

批量转换(1)

在某些情况下,你可能想一次性将所有角色配音 AudioClip 转换为 BakedData。在这种情况下,请使用 Window > uLipSync > Baked Data Generator

选择你想用于批量转换的 Profile,然后选择目标 AudioClips。如果 Input TypeList,直接注册 AudioClips(从 Project 窗口拖放多选很方便)。如果 Input TypeDirectory,会打开一个文件对话框让你指定一个目录,它会自动列出该目录下的 AudioClips

点击 Generate 按钮开始转换。

批量转换(2)

当你已经创建了数据,你可能想重新审视校准并更改配置文件。在这种情况下,每个 ProfileBaked Data 标签中有一个 Reconvert 按钮,它使用 Profile 转换所有数据。 时间轴

您可以在时间轴中为uLipSync添加特殊轨道和剪辑。然后我们需要绑定哪些对象将使用时间轴中的数据进行移动。为此,引入了一个名为uLipSyncTimelineEvent的组件,它接收播放信息并通知uLipSyncBlendShape。流程如下图所示。

设置

在时间轴的轨道区域右击,从uLipSync.Timeline > uLipSync Track添加专用轨道。然后在剪辑区域右击,从Add From Baked Data添加剪辑。您也可以直接将BakedData拖放到此区域。

选择剪辑时,您将在检查器中看到以下UI,您可以在此替换BakedData

接下来,向某个游戏对象添加uLipSyncTimelineEvent,然后添加绑定以便可以播放唇形同步。此时,在*On Lip Sync Update (LipSyncInfo)*中注册uLipSyncBlendShape

然后点击带有PlayableDirector的游戏对象,将游戏对象拖放到时间轴窗口中uLipSyncTrack的绑定槽中。

现在唇形同步信息将发送到uLipSyncTimelineEvent,并与uLipSyncBlendShape建立连接。在编辑时也可以进行播放,因此您可以与动画和声音一起调整。

时间轴设置助手

Window > uLipSync > Timeline Setup Helper

此工具自动创建与AudioTrack中注册的剪辑相对应的BakedData,并将其注册到uLipSync Track中。

动画烘焙

您还可以将预先计算的唇形同步数据BakedData转换为AnimationClip。将其保存为动画可以轻松地与其他动画组合,将其集成到现有工作流程中,并通过移动关键帧later进行调整。示例场景是Samples / 07. Animation Bake

设置

选择Window > uLipSync > Animation Clip Generator以打开uLipSync Animation Clip Generator窗口。

要运行动画烘焙,您需要打开已设置uLipSyncBlendShape组件的场景。然后,请将场景中的组件设置到此窗口的字段中。

  • Animator
    • 选择场景中的Animator组件。
    • AnimationClip将从此Animator开始的层次结构中创建。
  • Blend Shape
    • 选择场景中存在的uLipSyncBlendShape组件。
  • Baked Data List
    • 选择要转换为AnimationClip的BakedData资产。
  • Sample Frame Rate
    • 指定要添加关键帧的采样率(fps)。
  • Threshold
    • 只有当权重变化超过此值时才会添加关键帧。
    • 权重的最大值为100,因此10表示当权重变化10%时。
  • Output Directory
    • 指定要输出烘焙动画剪辑的目录。
    • 如果目录为空,则在Assets(根目录)下创建。

以下图片是一个示例设置。

Threshold从0、10和20变化,您将得到以下结果。

纹理

uLipSyncTexture允许您根据识别的音素更改纹理和UV。Samples / 08. Texture是一个示例场景。

  • Renderer
    • 指定要更新的材质的Renderer
  • Parameters
    • Min Volume
      • 更新的最小音量值(log10)。
    • Min Duration
      • 保持嘴部使用相同纹理/uv的最短时间。
  • Textures
    • 在这里您可以选择要分配的纹理
    • Phoneme
      • 输入Profile中注册的音素(例如"A"、"I")。
      • 空字符串("")将被视为没有音频输入。
    • Texture
      • 指定要更改的纹理。
      • 如果未指定,将使用材质中设置的初始纹理。
    • UV Scale
      • UV缩放。对于平铺纹理,指定此值。
    • UV Offset
      • UV偏移。对于平铺纹理,指定此值。

动画器

uLipSyncAnimator可用于使用AnimatorController进行唇形同步。创建一个仅应用于嘴部的Avatar Mask的Layer,如下所示,并设置一个Blend Tree,使每个嘴型通过参数移动。

然后将音素和相应的AnimatorController参数设置到uLipSyncAnimator中,如下所示。

示例场景是Samples / 09. Animator

VRM支持

VRM是一种独立于平台的文件格式,专为3D角色和头像设计。在VRM 0.X中,通过VRMBlendShapeProxy控制混合形状,而在1.0版本中,混合形状被抽象为Expression并通过VRM10ObjectExpression控制。

VRM 0.X

使用uLipSyncBlendShape时,直接控制了SkinnedMeshRenderer中的混合形状,但有一个名为uLipSyncBlendShapeVRM的修改组件,它改为控制VRMBlendShapeProxy

VRM 1.0

通过使用uLipSyncExpressionVRM,您可以控制VRM10ObjectExpression

示例

有关更多详细信息,请参阅Samples / VRM。在此示例中,使用uLipSyncExpressionVRM进行VRM 1.0的设置。

脚本定义符号

从.unitypackage安装VRM包时,需要手动添加Scripting Define Symbols。对于VRM 0.X,添加USE_VRM0X,对于VRM 1.0,添加USE_VRM10。如果通过Package Manager添加包,这些符号会自动添加。

运行时设置

如果你动态生成模型,需要自行设置和连接 uLipSyncuLipSyncBlendShape10. Runtime Setup 中包含了一个示例。你将动态地将这些组件附加到目标对象并按如下方式设置:

[System.Serializable]
public class PhonemeBlendShapeInfo
{
    public string phoneme;
    public string blendShape;
}

public GameObject target;
public uLipSync.Profile profile;
public string skinnedMeshRendererName = "MTH_DEF";
public List<PhonemeBlendShapeInfo> phonemeBlendShapeTable = new List<PhonemeBlendShapeInfo>();

uLipSync.uLipSync _lipsync;
uLipSync.uLipSyncBlendShape _blendShape;

void Start()
{
    // 设置 uLipSyncBlendShape
    var targetTform = uLipSync.Util.FindChildRecursively(target.transform, skinnedMeshRendererName);
    var smr = targetTform.GetComponent<SkinnedMeshRenderer>();

    _blendShape = target.AddComponent<uLipSync.uLipSyncBlendShape>();
    _blendShape.skinnedMeshRenderer = smr;

    foreach (var info in phonemeBlendShapeTable)
    {
        _blendShape.AddBlendShape(info.phoneme, info.blendShape);
    }

    // 设置 uLipSync 并将其与 uLipSyncBlendShape 连接
    _lipsync = target.AddComponent<uLipSync.uLipSync>();
    _lipsync.profile = profile;
    _lipsync.onLipSyncUpdate.AddListener(_blendShape.OnLipSyncUpdate);
}

然后将此组件附加到某个 GameObject 上,提前准备好必要的信息并创建预制体或其他内容。该示例包括常规 SkinnedMeshRenderer 的设置和 VRM 1.0 的设置。

用户界面

当你想在运行时创建、加载、保存 Profile,或添加音素并进行校准时,你需要一个用户界面。11. UI 添加了一个简单的示例。通过修改它,你可以创建自己的自定义用户界面。

提示

自定义事件

uLipSyncBlendShape 用于 3D 模型,uLipSyncTexture 用于 2D 纹理。但如果你想做一些不同的事情,可以编写自己的组件来支持它们。准备一个提供接收 uLipSync.LipSyncInfo 函数的组件,并将其注册到 uLipSyncuLipSyncBakedDataPlayerOnLipSyncUpdate(LipSyncInfo)

例如,以下是一个简单脚本的示例,它将识别结果输出到 Debug.Log()

using UnityEngine;
using uLipSync;

public class DebugPrintLipSyncInfo : MonoBehaviour
{
    public void OnLipSyncUpdate(LipSyncInfo info)
    {
        if (!isActiveAndEnabled) return;

        if (info.volume < Mathf.Epsilon) return;

        Debug.LogFormat($"PHONEME: {info.phoneme}, VOL: {info.volume} ");
    }
}

LipSyncInfo 是一个具有以下成员的结构。

public struct LipSyncInfo
{
    public string phoneme; // 主要音素
    public float volume; // 归一化音量(0 ~ 1)
    public float rawVolume; // 原始音量
    public Dictionary<string, float> phonemeRatios; // 包含音素及其比率的表
}

导入/导出 JSON

有一个功能可以将配置文件保存到 JSON 或从 JSON 加载。在编辑器中,从 Import / Export JSON 标签指定要保存或加载的 JSON,然后点击 ImportExport 按钮。

如果你想在代码中执行此操作,可以使用以下代码。

var lipSync = GetComponent<uLipSync>();
var profile = lipSync.profile;

// 导出
profile.Export(path);

// 导入
profile.Import(path);

运行时校准

如果你想在运行时执行校准,可以通过使用 uLipSync.RequestCalibration(int index)uLipSync 发出请求来实现,如下所示。从当前播放的声音计算出的 MFCC 将被设置到指定的音素。

lipSync = GetComponent<uLipSync>();

for (int i = 0; i < lipSync.profile.mfccs.Count; ++i)
{
    var key = (KeyCode)((int)(KeyCode.Alpha1) + i);
    if (Input.GetKey(key)) lipSync.RequestCalibration(i);
}

请参考 CalibrationByKeyboardInput.cs 了解它的实际工作原理。另外,最好在构建应用程序后将配置文件保存并恢复为 JSON,因为对 ScriptableObject 的更改无法保存。

更新方法

Update Method 可用于调整使用 uLipSyncBlendShape 更新混合形状的时机。每个参数的描述如下。

方法时机
LateUpdateLateUpdate(默认)
UpdateUpdate
FixedUpdateFixedUpdate
LipSyncUpdateEvent收到 LipSyncUpdateEvent 后立即
External从外部脚本更新(ApplyBlendShapes()

WebGL

当将 WebGL 设置为目标平台时,会出现一个小的 UI 添加。

在 WebGL 中,由于自动播放策略,除非与页面内容进行交互(如点击),否则音频不会播放。然而,由于 Unity 内部仍在播放声音,这会导致原本应该从一开始就播放的音频不同步。启用 Auto Audio Sync On Web GL 将在用户交互发生时纠正这种差异。

Audio Sync Offset Time 可用于调整唇形同步延迟的时机。在内部,由于 WebGL 中无法使用 OnAudioFilterRead(),因此使用 AudioClip.GetData() 代替。这种方法利用了略微调整正在检索的缓冲区位置的能力。

目前,Unity 不支持 WebGL 的 JobSystem 和 Burst,这意味着性能不是最佳的。对于不需要实时分析的情况,建议预先烘焙数据。

Mac 构建

在 Mac 上构建时,你可能会遇到以下错误。

Building Library/Bee/artifacts/MacStandalonePlayerBuildProgram/Features/uLipSync.Runtime-FeaturesChecked.txt failed with output: Failed because this command failed to write the following output files: Library/Bee/artifacts/MacStandalonePlayerBuildProgram/Features/uLipSync.Runtime-FeaturesChecked.txt

这可能与麦克风访问代码有关,可以通过在 Project Settings > Player's Other Settings > Mac Configuration > Microphone Usage Description 中写入一些内容来修复。

从 v2 到 v3 的过渡

从 v3.0.0 开始,MFCC 的值已被修正为更准确的值。因此,如果你从 v2 过渡到 v3,你需要重新校准并创建一个新的 Profile

第三方许可

Unity-chan

示例包含 Unity-chan 资产。

© Unity Technologies Japan/UCL

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号