HarmonyOS 7 新特性(二十八)|Audio Kit 后台录音与无声排障

HarmonyOS 7(API 26)Beta2 配套资料新增后台录音、录制流选型与音频快照排障指导。后台采集涉及麦克风权限、长时任务和隐私提示,具体接口与上架要求请以当前 Audio Kit 文档为准。
录音功能在前台正常,并不代表退到后台后仍可靠。系统可能挂起应用,蓝牙或耳机切换可能改变输入设备,通话会触发并发策略,错误的 SourceType 还会造成“回调有数据但实际无声”。高质量录音必须把权限、流类型、生命周期、文件写入和诊断证据连成一条链。
本文以会议录音为例,设计后台录音状态机、分段文件、音量探针和音频快照排障方案。
一、先选择正确录音方案
AudioCapturer 适合获取 PCM 并自行处理;若需要直接生成常见封装格式,可选择相应媒体录制方案;低时延采集只用于确有耳返或实时处理需求的场景。不要因为“更快”就默认启用低时延,它会增加调度和功耗压力。
普通会议录音、语音识别、VoIP 和直播的 SourceType 不同。错误类型会影响通路、算法、并发和输入设备。
二、状态机覆盖前后台
type RecorderState =
| { kind: 'idle' }
| { kind: 'preparing'; sessionId: string }
| { kind: 'recording'; sessionId: string; segment: number }
| { kind: 'paused'; sessionId: string; reason: string }
| { kind: 'stopping'; sessionId: string }
| { kind: 'failed'; sessionId?: string; code: string }
interface RecordingSession {
sessionId: string
startedAt: number
sourceType: string
sampleRate: number
channelCount: number
}
页面只订阅状态,不直接持有 Capturer。这样页面销毁或旋转不会意外释放后台任务。
三、启动顺序必须可观测
推荐按“权限—参数—创建—监听—启动—确认 RUNNING—读数据—写文件”执行。每一步记录稳定事件和错误码,禁止把所有异常都显示为“录音失败”。
async function startRecording(config: RecorderConfig) {
await permission.ensureMicrophone()
validateConfig(config)
const capturer = await audioFactory.create(config)
capturer.onStateChange(onStateChange)
capturer.onReadData(onAudioData)
await capturer.start()
if (capturer.state !== 'RUNNING') throw new Error('STATE_NOT_RUNNING')
return capturer
}
具体 API 名称以当前 SDK 为准,这里的重点是顺序与证据。

四、后台录音需要长时任务
用户明确开始录音后,应用进入后台仍需持续采集,应按官方要求申请长时任务并展示持续可感知提示。进入后台前确认任务已建立,结束录音时立即停止任务。
class BackgroundRecordingGuard {
private active = false
async enter(sessionId: string) {
if (this.active) return
await backgroundTask.start({ type: 'audio-recording', sessionId })
this.active = true
}
async leave() {
if (!this.active) return
await backgroundTask.stop()
this.active = false
}
}
权限被撤销或系统终止任务后,状态机必须进入可解释终态。
五、分段写入降低损坏风险
长时间录音不要只写一个巨大临时文件。按时间或大小切分片段,每段完成后关闭句柄、计算哈希并更新 Manifest。崩溃后可恢复已完成片段。
interface AudioSegment {
index: number
path: string
startedAt: number
durationMs: number
bytes: number
sha256?: string
}
interface RecordingManifest {
sessionId: string
segments: AudioSegment[]
finalized: boolean
}
文件路径存放在受控目录,最终保存或分享前再让用户确认。
六、用振幅探针提前发现无声
能够收到回调不代表有效录音。周期计算短窗 RMS 或最大振幅,若连续一段时间接近零,结合静音、输入设备和业务场景提示用户检查。
function rms(samples: Int16Array): number {
if (!samples.length) return 0
let sum = 0
for (const value of samples) sum += value * value
return Math.sqrt(sum / samples.length) / 32768
}
function isProbablySilent(history: number[]): boolean {
return history.length >= 10 && history.every(value => value < 0.002)
}
安静环境可能确实无声,因此不要自动停止,只提供清晰诊断入口。
七、设备切换与并发打断
监听输入设备、录音流状态和系统打断。蓝牙断开后重新确认路由;通话到来时根据业务规则暂停或结束;恢复后新建片段,避免把不同参数的数据拼进同一 PCM 文件。
function onRouteChanged(route: InputRoute) {
telemetry.event('audio_route_changed', { type: route.type })
if (!route.available) recorder.pause('input-device-lost')
else recorder.reconfigure(route)
}
不要在回调线程执行耗时编码或网络上传,数据通过有界队列交给工作线程。
八、音频快照用于现场定位
无声问题出现时,音频快照可以提供当前进程音频子系统状态。快照应由用户或受控诊断流程触发,附带会话 ID、状态变化和路由事件,但不包含不必要的录音内容。
采集后先本地检查大小与敏感字段,再进入受控上传。生产环境设置频率和存储上限。
九、停止流程也要可恢复
先停止读取,再刷新编码器,关闭文件句柄,更新 Manifest,最后释放 Capturer 与长时任务。任何一步失败都继续执行后续清理,并把未完成状态留给下次启动恢复。
async function stopSafely(resources: RecorderResources) {
const errors: string[] = []
for (const job of [resources.stopCapture, resources.flush, resources.closeFile, resources.stopBackground]) {
try { await job() } catch (error) { errors.push(String(error)) }
}
return errors
}
十、验收矩阵
覆盖首次拒绝权限、后台 30 分钟、锁屏、来电、蓝牙切换、耳机插拔、存储不足、进程终止和恢复。记录启动成功率、首个数据延迟、丢帧率、静音误报、文件可播放率、功耗与温升。
十一、上线清单
- 根据业务选择正确 SourceType 与录音方案;
- 状态机由服务层持有,不依赖页面生命周期;
- 后台录音已接入长时任务和持续提示;
- PCM 队列有上限,编码不阻塞回调;
- 长录音分段、落盘并可崩溃恢复;
- 输入设备、打断和静音都有诊断;
- 停止路径即使部分失败也完成清理;
- 真机前后台与外设矩阵已验证。

结语
后台录音的难点不是调用 start,而是持续证明“系统仍在采、数据有效、文件安全、用户知情”。用服务级状态机管理生命周期,用分段文件保护结果,再用振幅探针和音频快照缩短排障,才能把录音从演示功能做成可靠工具。
官方参考
- 录音无声定位指导:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/audio-recording-no-audio-troubleshooting
- 音频录制概述:https://developer.huawei.com/consumer/cn/doc/doccenter-feature-dev/bpta-audio-record-overview
更多推荐



所有评论(0)