Instructions to use Sky-Kim/com.sky.sentis.audio2lipsync with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- unity-sentis
How to use Sky-Kim/com.sky.sentis.audio2lipsync with unity-sentis:
string modelName = "[Your model name here].sentis"; Model model = ModelLoader.Load(Application.streamingAssetsPath + "/" + modelName); IWorker engine = WorkerFactory.CreateWorker(BackendType.GPUCompute, model); // Please see provided C# file for more details
- Notebooks
- Google Colab
- Kaggle
Sentis Audio2Lipsync (com.sky.sentis.audio2lipsync)
A Unity package for on-device, audio-driven lipsync built on Unity Sentis
(com.unity.ai.inference 2.6.1). It is a port of
aaryansachdeva/unreal-audio2lipsync
(weights): HuBERT-Large followed by a transformer
decoder that predicts 52 ARKit blendshapes at 60 fps from 16 kHz audio. You don't need the Python
server: the model runs inside Unity, and the server's chunking and post-processing are reimplemented in C#.
Install
The package keeps its model files in Git LFS, so install git-lfs before Unity resolves the package.
Packages/manifest.json:
"com.sky.sentis.audio2lipsync": "https://huggingface.co/Sky-Kim/com.sky.sentis.audio2lipsync.git"
You can also use Package Manager → + → Install package from git URL… with the same URL.
Requirements: Unity 6 (tested on 6000.3.23f1) and com.unity.ai.inference 2.6.1. The demo sample also
needs URP, the Input System and uGUI.
Quick start
There is no model setup step. In the editor the model loads straight from the package's Model~
folder. When you build a player, a build hook copies it into StreamingAssets/Audio2Lipsync/ and
removes it again after the build. To use your own model, put an audio2lipsync.sentis in
StreamingAssets/Audio2Lipsync/; it takes precedence over the packaged one.
- Add a
BlendshapePlayer(it requires anAudioSource) to your character and assign itsSkinnedMeshRenderers. EditmeshNamesif your rig doesn't use the sample head's blendshape names. - Generate the frames and play them:
using Audio2Lipsync;
using Unity.InferenceEngine;
var runner = await Audio2LipsyncRunner.CreateAsync(BackendType.GPUCompute); // loads the packaged model
runner.Warmup(); // one silent pass: shader compile + CFG baseline
float[] audio16k = AudioUtils.ToMono16k(clip); // any AudioClip -> mono 16 kHz
float[] frames = await runner.GenerateAsync(audio16k, LipsyncSettings.Default); // [n * 52] @ 60 fps
player.Play(frames, clip); // locked to the AudioSource clock
// ...
runner.Dispose();
Demo sample
Import it from Package Manager â–¸ Sentis Audio2Lipsync â–¸ Samples â–¸ Demo, open
Scenes/Audio2LipsyncDemo.unity and press Play. Tools â–¸ Audio2Lipsync â–¸ Build Demo Scene rebuilds the
scene from code. It also sets a default Microphone Usage Description, which iOS and macOS player builds
require.
- Generate & Play (or
Space) runs the selected clip (EN / DE / JA / KO). - Record (Mic) → Stop & Lipsync runs microphone audio.
- The sliders set gain, CFG scale, smoothing window and silence gate.
Package layout
| Path | Contents |
|---|---|
Runtime/Audio2LipsyncRunner.cs |
Owns the worker. Splits audio into 3 s chunks with a 30-frame crossfade and overlap-adds them. Provides warmup, Generate and GenerateAsync, which uses async readback. |
Runtime/LipsyncPostProcess.cs |
Port of server.py run_inference: CFG → clip → mouth-only mask → centered gain → smoothing → RMS silence gate → fades. |
Runtime/BlendshapePlayer.cs |
Maps ARKit names to mesh blendshapes and plays them at 60 fps. Also drives tongue_ and teeth_ variants. |
Runtime/AudioUtils.cs |
Mono downmix and a windowed-sinc resampler to 16 kHz. |
Runtime/Audio2LipsyncModel.cs |
Finds and loads the model: the package in the editor, StreamingAssets in players (UnityWebRequest on Android and WebGL). |
Editor/Audio2LipsyncBuildHook.cs |
Copies the model into StreamingAssets for each player build and cleans it up afterwards, including after a failed build. |
Editor/Audio2LipsyncSerializer.cs |
Serializes an imported ONNX to .sentis (fp32, or optional Float16/Uint8). |
Model~/audio2lipsync.sentis |
The model, fp32 weights, 1.3 GB. |
Samples~/Demo |
Sample head, dialogue clips, demo manager and a code-built UGUI scene. |
Tools~/export_onnx.py, Tools~/compare_clip.py |
Export to ONNX from best.pt, and comparison against the original server. |
Model I/O: input is audio [1, 48000] (3 s, 16 kHz mono, raw). Output is blendshape [1, 180, 52]
(ARKit order, de-normalized, not clipped).
Accuracy and speed
Measured on Apple Silicon with Unity 6000.3.23f1 and Sentis 2.6.1:
| Check | Result |
|---|---|
| torch vs ONNX Runtime (3 s speech chunk) | max abs diff 6.1e-6 |
torch vs Sentis, packaged .sentis, GPUCompute / CPU |
4.7e-6 / 4.5e-6 |
| Original server pipeline vs Unity, full 3.87 s clip | max abs diff < 1e-4 (JawOpen corr 1.0000) |
| Warm time per 3 s chunk, GPUCompute / CPU | ~45 ms / ~320 ms |
Differences from the reference server
- Chunk normalization: HuBERT-Large normalizes the waveform with
F.layer_norm(x, x.shape). The server batches its chunks, so that normalization spans every chunk in the batch and the chunks affect each other. Here each chunk is normalized on its own, which matches the server withMAX_CHUNK_BATCH=1. - Exported layer norm: the export writes that normalization out as mean/variance ops, because the
Sentis importer rejects a rank-2
LayerNormalizationscale. - Short clips: clips of 3 s or less are zero-padded to 3 s, the same way the server pads its last chunk.
- Resampling: done in C# with a windowed-sinc filter. The server uses
torchaudio.functional.resample.
License
MIT — see LICENSE.md. This package includes:
- Weights converted from fotonlabs/unreal-audio2lipsync (MIT).
- The HuBERT-Large encoder from fairseq via torchaudio (MIT).
- The sample head and dialogue audio from skykim/NeuroSync_Unity (MIT).
- Downloads last month
- 12
Model tree for Sky-Kim/com.sky.sentis.audio2lipsync
Base model
fotonlabs/unreal-audio2lipsync