应采用recorder-core的powerLevel做跨端能量估算,配合CSS竖条动画实现类微信动态波形;因onFrameRecorded在小程序/iOS/App端不支持或不稳定,且App端无法获取PCM帧,故放弃实时canvas绘图方案。

不能在 App 端用 canvas 实时画真实波形,也不能依赖 onFrameRecorded 在小程序/H5 全平台稳定工作——得换思路:用 recorder-core 的 powerLevel 做能量估算,再配合 CSS 动画或轻量 canvas 渲染“类微信”动态反馈。
为什么直接 canvas + onFrameRecorded 行不通
微信小程序基础库 2.25.0+ 才实验性支持 onFrameRecorded,iOS 上基本不触发;App 端(Android/iOS)的 uni.getRecorderManager() 根本不提供 PCM 帧,frameBuffer 永远为空;H5 虽可用 MediaRecorder,但格式兼容、权限策略、内存占用都不稳定。
常见错误现象:onFrameRecorded 回调没执行、canvas 画布空白、真机上波形卡死或跳变——不是代码写错,是平台能力缺失。
- App 端只能走「录完再解析」路线,实时波形无解
- 小程序端即使监听到帧,数据也是稀疏且延迟的,无法支撑 30fps 波形动画
- H5 端若用 Web Audio API 分析,需额外处理
getUserMedia权限和音频上下文激活问题
用 recorder-core 的 powerLevel 替代真实 PCM
recorder-core 内置的 powerLevel 是一个毫秒级更新的振幅估算值(范围 0–1),不依赖原始音频流,跨 H5/小程序/App 三端一致,且开销极低。
它不是真实波形,但足够模拟“声音有无 + 强弱变化”,视觉上接近微信按住说话时的呼吸感波形条。
一站式排查小程序隐私授权报错(errno 104 / buttonId is wrong 等)+ 标准修改模式。适用:隐私协议配置、隐私弹窗不弹、授权报错、隐私接口调用失败。已抽离具体项目,适用于任何微信小程序。
- 初始化时传入
{autoStart: false, usePowerLevel: true} - 启动录音后,
recorder.on('powerLevel', (level) => {...})可每 ~50ms 触发一次 - level 值可直接映射为柱状图高度:
height = Math.max(8, level * 64)(单位 rpx) - 避免高频重绘:用
requestAnimationFrame或节流(如 20fps)控制更新频率
UI 层怎么渲染“动态波形”才像微信
别用 canvas 绘制复杂路径,微信实际用的是横向排列的 10–12 根等宽竖条,靠 height + opacity 变化营造律动感。CSS 方案更轻、更稳、兼容性更好。
示例结构(audio-wave.vue):
<template>
<view class="wave-container">
<view
v-for="(h, i) in heights"
:key="i"
class="wave-bar"
:style="{ height: h + 'rpx', opacity: 0.3 + h / 80 }"
/>
</view>
</template>- 维护一个长度为 10 的
heights数组,每次新powerLevel到来时heights.shift(); heights.push(newHeight) - 用
v-for渲染,避免 dom 频繁增删 - opacity 随高度渐变,增强“声波扩散”观感
- 不要加 transition:会拖慢响应,微信是硬切换
App 端必须绕过 recorderManager 做原生桥接
如果 UI 要求更高(比如带频谱色彩、左右声道分离),App 端唯一可行路径是调用原生插件返回频域能量数组,而非前端解析音频文件。
例如:uni.requireNativePlugin('AudioAnalyzer').getSpectrum() 返回 [0.12, 0.45, 0.88, ...](32 段),前端只负责映射绘制。
- WebAssembly 解码(如 ffmpeg.wasm)在 App 端首帧延迟常超 3s,不适合语音消息场景
- 纯 JS 解析 mp3/wav 文件体积大、CPU 占用高,低端安卓机易卡顿
- 原生插件返回的数据量小(
- 没有原生能力时,退化为“伪波形”:用
powerLevel+ 插值生成平滑波动,比随机抖动更可信
真正难的不是怎么画,是怎么让三端都“看起来在响”。真实波形是奢侈品,能量反馈才是刚需——别在 App 里死磕 canvas,那条路根本没出口。


















