Flutter中如何实现音频与Lottie/Rive动画的同步?
Lottie/Rive 与音频并行播放的同步解决方案
这个需求属于动效落地的常见场景,目前已经有成熟的落地方案可以完全解决10-15分钟时长的音画同步问题,具体实现逻辑如下:
- 核心原则:以音频进度为单一基准对齐动画,不要让音频和动画使用独立的时钟控制,二者的时钟漂移累积是音画不同步的核心原因。
- 前置准备:制作阶段在动画和音频的关键节点(比如角色台词开头、转场节点)预埋统一的同步标记,Lottie可以通过属性关键帧埋点,Rive可以直接在编辑器内添加自定义事件,后续作为校准的参考点。
- 播放端实现步骤:
- 资源预加载:等音频资源缓冲完成、动画首帧渲染完成后,再同时调用二者的播放接口,避免加载速度差异导致的初始偏移
- 定时校准:每300ms比对一次音频当前进度和动画当前进度,偏移超过100ms时直接把动画进度seek到对应位置,人耳对音频跳变的敏感度远高于画面小幅度跳帧,所以优先保证音频连续
- 关键节点强校验:到预埋的同步标记点时,强制校验一次二者进度,有偏移立即校准,避免误差累积
- 代码参考示例(Lottie + 原生Audio):
// 音频实例、Lottie动画实例 const audio = document.getElementById('audio') const anim = lottie.loadAnimation({ container: document.getElementById('anim'), path: 'xxx.json' }) let isPlaying = false // 等待资源全部加载完成 Promise.all([ new Promise(res => audio.addEventListener('canplaythrough', res)), new Promise(res => anim.addEventListener('DOMLoaded', res)) ]).then(() => { // 同时启动播放 audio.play() anim.play() isPlaying = true }) // 定时校准 setInterval(() => { if (!isPlaying) return // 动画帧率假设为30,按实际帧率换算即可 const currentAnimTime = (anim.currentFrame / 30) * 1000 const currentAudioTime = audio.currentTime * 1000 const diff = currentAudioTime - currentAnimTime // 偏移超过100ms执行校准 if (Math.abs(diff) > 100) { anim.goToAndPlay(audio.currentTime * 30, true) } }, 300)
Rive场景下实现逻辑完全一致,仅需将动画的进度查询、seek、加载完成监听的API替换为Rive官方提供的对应接口即可。按照上述方案实现,15分钟时长的动画播放偏移可以稳定控制在50ms以内,人眼和人耳都感知不到差异,已经在大量商用H5、短视频生成工具中落地验证。
内容的提问来源于stack exchange,提问作者ecywyv
相关产品推荐
相关产品推荐

