锅铲声保住了,人声却糊了:HarmonyOS 7 AudioCapturer 三种降噪模式怎么选
锅铲声保住了,人声却糊了:HarmonyOS 7 AudioCapturer 三种降噪模式怎么选
同一个录音入口被拿来做三件事:录炒菜的锅气声、录菜谱讲解、在嘈杂厨房里记一条语音备忘。旧实现只开一个固定“降噪”开关,结果锅铲和油爆声被抹平,纯人声仍有空调底噪,切换场景后页面还不知道设备最终采用了哪种模式。
HarmonyOS 7(API 26)为 AudioCapturer 增加了三种可区分的降噪模式,以及“查询支持、设置模式、读回当前模式”的完整链路。本文交付一套按录音意图选模式的控制器、两种行为明显不同的核心案例、一个嘈杂环境补充案例,以及可复用验收矩阵。

图中的顺序不能颠倒:先查询设备支持的模式,再按录音意图选择,设置后读回确认;请求模式不受支持时走明确降级,而不是假装已经生效。
官方依据与版本边界
官方变更页:https://developer.huawei.com/consumer/cn/doc/doccenter-release-notes/js-apidiff-audiokit-7003
- API 26 新增
NoiseReductionMode枚举。 - 枚举包含
FIDELITY = 0、PURE_VOCALS = 1、STANDARD = 2。 AudioCapturer.setNoiseReductionMode(mode)用于设置降噪模式。AudioCapturer.getNoiseReductionMode()用于读取当前模式。AudioCapturer.getSupportedNoiseReductionModes()返回当前设备支持的模式集合。
本文依据 HarmonyOS 7.0.0 Release(API 26)Audio Kit 官方变更说明核对接口,并对模式选择、能力交集和降级逻辑做宿主侧 TypeScript 断言。当前本机 SDK 为 API 24,且没有连接 HDC 设备,因此不把示例描述为 API 26 编译通过、设备录音效果或信噪比实测。接入前请在 API 26 工程和目标设备上完成编译、听感盲测、波形与读回验证。
不要把三种模式写成“强、中、弱”
三种模式的差别不是简单的降噪强度滑杆,而是目标不同:
FIDELITY:优先保留环境和细节,适合记录烹饪声、器具声等内容本身。PURE_VOCALS:录音目标是清晰人声,环境声不属于交付物。STANDARD:没有单一主角,或当前场景只需要通用的噪声控制。
如果产品只显示“降噪:开”,用户无法理解为什么一段录音保留了锅铲声,另一段却把环境压下去了。更合适的交互是让业务场景决定首选模式,同时把最终读回模式记入录音元数据。
两种接入架构:固定模式与运行时协商
本篇属于 Audio Kit 采集可靠性系列的“模式协商”一环。模式选择发生在录制开始前,属于采集器配置;录音页只持有用户意图和最终读回值,不直接保存“设备一定支持某模式”的假设。
- 方案 A:在每个录音页面写死一个模式。只有设备范围已锁定、功能单一且支持集合经过逐机验证时才适用。实现短,但换设备或切换录音意图时容易出现请求值和实际值分离;每个页面还会重复处理错误。
- 方案 B:由 NoiseReductionPolicy.ets 统一把录音意图映射为候选序列,AudioCaptureFactory.ets 在录制前查询设备支持集合、设置、读回,再把 requested/applied/degraded 交给页面。多场景和多设备优先用此方案;代价是多一次能力探测与显式状态管理。
比较的关键不是哪一档“更强”,而是谁拥有设备能力事实。无论采用哪种方案,页面上显示的都必须是读回的 applied,而非按钮刚发出的 requested。
可复用的 ArkTS 模式控制器
下面的控制器接收一个已经创建好的 AudioCapturer。它先查询支持列表,再从候选顺序中选择第一个可用模式;设置后必须读回,避免 UI 只显示“请求成功”。
import { audio } from '@kit.AudioKit'
type RecordingIntent = 'cooking-sound' | 'recipe-narration' | 'kitchen-memo'
type AppliedNoiseReduction = {
requested: audio.NoiseReductionMode
applied: audio.NoiseReductionMode
degraded: boolean
}
function preference(intent: RecordingIntent): audio.NoiseReductionMode[] {
switch (intent) {
case 'cooking-sound':
return [
audio.NoiseReductionMode.FIDELITY,
audio.NoiseReductionMode.STANDARD
]
case 'recipe-narration':
return [
audio.NoiseReductionMode.PURE_VOCALS,
audio.NoiseReductionMode.STANDARD
]
case 'kitchen-memo':
return [
audio.NoiseReductionMode.STANDARD,
audio.NoiseReductionMode.PURE_VOCALS
]
}
}
export function applyNoiseReduction(
capturer: audio.AudioCapturer,
intent: RecordingIntent
): AppliedNoiseReduction {
const supported = capturer.getSupportedNoiseReductionModes()
const candidates = preference(intent)
const requested = candidates[0]
const selected = candidates.find(mode => supported.includes(mode))
if (selected === undefined) {
throw new Error('No supported noise reduction mode for current intent')
}
capturer.setNoiseReductionMode(selected)
const applied = capturer.getNoiseReductionMode()
if (applied !== selected) {
throw new Error("Noise reduction readback mismatch selected=" + selected + " applied=" + applied)
}
return {
requested,
applied,
degraded: applied !== requested
}
}
这里没有用枚举数值比较“大小”。模式是语义选择,不存在数值越大效果越强的官方结论。候选顺序来自业务意图,支持集合来自设备,最终结果来自读回。
案例一:烹饪声教程优先 FIDELITY
煎、炸、翻炒时的声音本身就是内容。若把持续油声和锅铲碰撞都当作噪声,观众会失去判断火候的重要线索。
这个场景的主路径是:
- 首选
FIDELITY。 - 设备不支持时降级到
STANDARD。 - 录音页明确展示“保真”或“标准降噪”,不能仍显示首选值。
- 试听样本要同时包含轻微翻炒和瞬时锅铲声,不能只用一段说话声验收。
它的成功标准不是“背景越安静越好”,而是关键烹饪细节没有被错误抹除,同时没有不可接受的底噪。
案例二:菜谱旁白优先 PURE_VOCALS
旁白的交付物是语句清晰度。风扇、抽油烟机和远处器具声不属于内容主体,因此首选 PURE_VOCALS,不支持时再用 STANDARD。
import { hilog } from '@kit.PerformanceAnalysisKit'
const result = applyNoiseReduction(capturer, 'recipe-narration')
AppStorage.setOrCreate('noiseReductionApplied', result.applied)
AppStorage.setOrCreate('noiseReductionDegraded', result.degraded)
hilog.info(
0x1200,
'RecipeAudio',
'requested=%{public}d applied=%{public}d degraded=%{public}s',
result.requested,
result.applied,
String(result.degraded)
)
旁白场景还要增加一个反例:说话人短暂停顿时,系统不能把恢复的环境底噪误判为内容开始;验收应包含有声、停顿、再次说话三段,而不是只听一句完整句子。
补充案例:厨房语音备忘优先 STANDARD
语音备忘既要听清人声,又不值得为每条记录做复杂调参。STANDARD 是更稳妥的默认选择。若设备不支持,再根据支持集合选择 PURE_VOCALS,并把降级状态记录下来。
这个案例与旁白不同:旁白用于正式内容,应该阻止“不受支持且无候选”的录制;备忘是即时工具,即使只能使用可用模式也应允许继续,但必须把实际模式写入元数据,便于后续解释音质差异。
失败与恢复:读回不一致不能继续录制
setNoiseReductionMode 没有返回“听感已符合预期”的证据。设置抛错、支持集合为空或读回值不是刚选中的模式时,录音入口应进入可解释的失败状态:撤回本次模式标签,保留 sessionId、intent、supported、selected、applied 和错误码的结构化日志,再让用户选择通用模式或停止录制。不要在异常后沿用上一段录音的 UI 标签。页面退出时仍须停止并释放采集器,避免旧实例继续占用麦克风。
诊断日志只记录模式元数据,不记录音频内容或个人信息。可用 hilog 将同一个 sessionId 下的“支持集合、请求模式、读回模式、降级原因”关联;上机时分别注入空支持集合、设置异常、读回不一致和页面中途退出,检查是否都能得到明确终态。宿主侧断言只能覆盖选择和状态分支,音质与设备行为仍需 API 26 工程和目标设备验证。
复现步骤
- 在 API 26 工程创建
AudioCapturer,保存设备型号、系统版本和采样配置。 - 调用
getSupportedNoiseReductionModes(),记录原始返回数组。 - 分别选择烹饪声、菜谱旁白和厨房备忘三种意图。
- 调用
setNoiseReductionMode()后立即用getNoiseReductionMode()读回。 - 每种模式录制同样长度的样本,保留原始文件、模式、时间和场景标签。
- 用主观听感、波形和可复现步骤比较,不编造信噪比提升数值。
- 构造“首选模式不受支持”的测试替身,确认 UI 和日志都显示实际降级。
验收矩阵
| 场景/输入 | 首选模式 | 验收信号 |
|---|---|---|
| 烹饪声教程 | FIDELITY | 锅铲和油爆细节保留 |
| 正式菜谱旁白 | PURE_VOCALS | 人声清楚,环境被抑制 |
| 厨房语音备忘 | STANDARD | 通用降噪,允许明确降级 |
| 首选受支持 | 设置首选 | 读回等于 requested |
| 首选不支持 | 选择候选 | degraded=true |
| 所有候选不支持 | 停止设置 | 返回明确错误 |
| 切换录音意图 | 重新设置并读回 | UI 不保留旧模式 |
| 页面销毁 | 停止录制并释放 | 无悬挂采集器 |
宿主侧选择逻辑测试
当前机器不能运行 API 26 的音频采集,因此先验证“意图、支持集合、候选顺序”的纯逻辑。它不能证明降噪听感,但能发现把不支持模式直接下发或把枚举当强度排序的问题。
type HostMode = 'FIDELITY' | 'PURE_VOCALS' | 'STANDARD'
function pickMode(preferred: HostMode[], supported: HostMode[]): HostMode | undefined {
return preferred.find(mode => supported.includes(mode))
}
const cases = [
{ preferred: ['FIDELITY', 'STANDARD'], supported: ['STANDARD'], expected: 'STANDARD' },
{ preferred: ['PURE_VOCALS', 'STANDARD'], supported: ['PURE_VOCALS'], expected: 'PURE_VOCALS' },
{ preferred: ['STANDARD', 'PURE_VOCALS'], supported: [], expected: undefined }
] as const
for (const item of cases) {
const actual = pickMode([...item.preferred], [...item.supported])
if (actual !== item.expected) {
throw new Error(`mode selection failed: ${JSON.stringify(item)}`)
}
}
文件级检查表
-
AudioCaptureFactory.ets只负责创建和释放采集器。 -
NoiseReductionPolicy.ets维护意图到候选模式的映射。 - 设置前查询设备支持列表,不硬编码“所有设备都支持”。
- 设置后读回实际模式,并把 requested/applied/degraded 写入日志。
- 三类录音使用不同验收素材,不拿旁白样本替代烹饪声测试。
- API 26 工程完成编译,目标设备完成录音、听感和生命周期验证。
- 不用宿主断言冒充设备音质、性能或降噪效果数据。
小结
FIDELITY、PURE_VOCALS 和 STANDARD 不是三档强弱,而是三种录音目标。真正稳妥的接入链路是:先查支持列表,按场景选候选,设置后读回,失败时明确降级。
这样做多了几行状态代码,却能避免最难解释的两类问题:用户以为已经启用某模式,设备实际没有采用;以及为了追求“更安静”,把本来属于内容的声音一起抹掉。
更多推荐



所有评论(0)