Audio & DSP & Output API
音频分析、频谱可视化、DSP 效果器管理、音频输出、ReplayGain。
Audio API - 音频分析
audio.subscribeSpectrum
订阅实时频谱数据。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
subscriptionId | string | 否 | 可选;默认 。 |
fftSize | integer | 否 | 可选;默认 1024。 |
event | string | 否 | 可选;默认 audio:spectrum。 |
fps | integer | 否 | 可选;默认 30。 |
bands | integer | 否 | 可选;默认 48。 |
返回值:
{
"success": true,
"subscriptionId": "spectrum_main",
"fftSize": 1024,
"bands": 48,
"fps": 30,
"event": "audio:spectrum"
}WARNING
fftSize 必须是 2 的幂(256, 512, 1024, 2048, 4096, 8192, 16384),否则返回错误。
低频分辨率
C++ 层会根据请求的频段数自动提升 FFT 大小(≥64 bands → 8192,≥32 bands → 4096),以确保低频区域有足够的 bin 分辨率。频谱处理流水线包括:对数频率映射、sub-bin 线性插值、三角滤波器 RMS 平滑、频率倾斜补偿(+1.5 dB/octave)、dB 归一化和 gamma 校正(0.8)。
订阅与事件语义
subscriptionId只在 low-levelfb2k.invoke('audio.*')场景下需要;SDKfb.audio.subscribeSpectrum()不公开它。- 若重复传入同一个
subscriptionId,语义是更新/覆盖该订阅。 - 默认
audio:spectrum与自定义event的 payload 都是{ spectrum: number[] }。
const subscriptionId = 'spectrum_main';
await fb2k.invoke('audio.subscribeSpectrum', {
subscriptionId,
fftSize: 1024,
bands: 96,
fps: 30,
event: 'audio:spectrum'
});
fb2k.on('audio:spectrum', (data) => {
renderVisualizer(data.spectrum); // 归一化值数组
});
await fb2k.invoke('audio.unsubscribeSpectrum', { subscriptionId });audio.unsubscribeSpectrum
取消订阅频谱数据,释放可视化流资源。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
subscriptionId | string | 否 | 可选;默认 。 |
返回值: { "success": true, "removed": 1, "subscriptionId": "spectrum_main" }
示例:
// 精确取消指定订阅
await fb2k.invoke('audio.unsubscribeSpectrum', {
subscriptionId: 'my-sub-id'
});
// 省略 subscriptionId 时,默认取消当前 caller 的全部频谱订阅
await fb2k.invoke('audio.unsubscribeSpectrum');audio.getSpectrum
手动获取当前频谱数据(轮询模式)。需要先调用 subscribeSpectrum。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
bands | integer | 否 | 可选;默认 0。 |
返回值:
{
"success": true,
"spectrum": [0.1, 0.3, 0.5, ...],
"fftSize": 1024,
"bands": 96
}轮询建议
手动轮询是支持的,适合低频 UI 刷新和调试;如果需要高频实时可视化,优先使用 audio:spectrum 事件流。
示例:
// 先订阅频谱
await fb2k.invoke('audio.subscribeSpectrum', { fftSize: 1024, bands: 96, fps: 30 });
// 手动获取当前频谱数据
const result = await fb2k.invoke('audio.getSpectrum', { bands: 96 });
if (result.success) {
console.log('频谱数据:', result.spectrum);
console.log('频段数:', result.bands);
console.log('FFT 大小:', result.fftSize);
}audio.getWaveform
获取当前播放流的短波形片段。需要先调用 subscribeSpectrum 启动可视化流。
注意
此 API 用于获取当前播放流的实时波形片段,不是离线文件波形。如需生成完整文件波形,请使用 audio.generateFullWaveform。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
duration | number | 否 | 可选;默认 0.05。 |
signed | boolean | 否 | 可选;默认 false。 |
返回值:
{ "success": true, "waveform": [0.01, 0.18, ...], "duration": 0.05, "signed": false }返回值范围
signed: false(默认):waveform为 dB 归一化幅度数组,范围0..1signed: true:waveform保留 PCM 极性,线性归一化到[-1, 1],适合绘制对称波形
示例:
// 先订阅频谱以启动可视化流
await fb2k.invoke('audio.subscribeSpectrum');
// 获取 0.1 秒的波形数据
const result = await fb2k.invoke('audio.getWaveform', { duration: 0.1 });
if (result.success) {
console.log('波形数据点数:', result.waveform.length);
console.log('持续时间:', result.duration);
}
// signed 模式:获取带正负极性的对称波形(适合绘制上下对称波形图)
const signed = await fb2k.invoke('audio.getWaveform', { duration: 0.1, signed: true });
// signed.waveform 范围 [-1, 1]audio.setChannelMode
设置频谱分析的声道模式。无效的 mode 值会自动规范化为 "default",返回值中的 mode 反映规范化后的结果。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
mode | string | 否 | 可选;默认 default。 |
- 返回值:
{ "success": true, "mode": "mono" }
示例:
// 设置为单声道模式
await fb2k.invoke('audio.setChannelMode', { mode: 'mono' });
// 设置为前置声道
await fb2k.invoke('audio.setChannelMode', { mode: 'front' });
// 非法模式自动回退为 default
const result = await fb2k.invoke('audio.setChannelMode', { mode: 'invalid' });
// result.mode === "default"audio.analyzeBPM
分析曲目的 BPM。首先从元数据 BPM 标签读取,若不存在则尝试流派估算。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
forceAnalysis | boolean | 否 | 可选;默认 false。 |
path | string | 否 | 可选;默认 。 |
返回值:
{ "success": true, "bpm": 128, "source": "metadata", "confidence": 1.0 }| source 值 | 含义 |
|---|---|
| "metadata" | 来自文件 BPM 标签 |
| "estimate" | 来自流派估算(confidence 较低) |
示例:
// 从元数据读取 BPM
const result = await fb2k.invoke('audio.analyzeBPM', {
path: 'E:\\\\Music\\\\song.flac'
});
console.log(`BPM: ${result.bpm}, 来源: ${result.source}`);
// 强制重新分析
const result2 = await fb2k.invoke('audio.analyzeBPM', {
path: 'E:\\\\Music\\\\song.flac',
forceAnalysis: true
});已废弃
此 API 为历史遗留接口,当前仅返回文件基本信息(duration、sampleRate、channels),不包含实际波形数据。请使用 audio.generateFullWaveform 代替,它提供完整的后台解码、缓存和事件通知功能。
audio.generateWaveform
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path | string | 否 | 可选;默认 。 |
resolution | integer | 否 | 可选;默认 800。 |
返回值: {"channels":"...","duration":"...","error":"...","requestedResolution":"...","sampleRate":"...","success":true}
audio.generateFullWaveform
生成完整文件波形数据,支持后台解码、缓存和异步事件通知。适用于进度条概览、波形卡片和章节预览。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
cueIndex | integer | 否 | 可选;默认 -1。 |
method | string | 否 | 可选;默认 rms。 |
path | string | 否 | 可选;默认 。 |
preferCache | boolean | 否 | 可选;默认 true。 |
resolution | integer | 否 | 可选;默认 256。 |
scale | string | 否 | 可选;默认 linear。 |
signed | boolean | 否 | 可选;默认 false。 |
返回值: {"cached":"...","channels":"...","duration":"...","method":"...","path":"...","resolution":"...","sampleRate":"...","scale":"...","signed":"...","status":"...","success":true,"taskId":"...","waveform":{}}
路径与 fallback 语义
- C++ 层会先解析
path|subsong:N,再 canonicalize 路径,并把同一 canonical path 用于handle_create()、解码器和缓存键。 - 若同时提供
cueIndex与path|subsong:N,最终以cueIndex为准。 - 若 cached info 的
duration、samplerate、channels不完整,会先尝试 direct file read;只有 direct read 仍不足时才会进入失败事件。 - 归一化策略: 采用 95th percentile 归一化 — 收集所有非零采样窗口值并排序,取第 95% 分位数作为归一化参考值,超出部分 clamp 到 1.0。这使 95% 的窗口使用完整动态范围,仅极端峰值被裁剪。含防极端数据保护:若 95th percentile < maxValue × 0.3,则回退到 maxValue 归一化。
示例:
const result = await fb2k.invoke('audio.generateFullWaveform', {
path: 'E:\\\\Music\\\\song.flac',
resolution: 256
});
if (result.taskId) {
fb2k.on('audio:fullWaveformReady', (e) => {
if (e.taskId === result.taskId) {
console.log('波形生成完成:', e.waveform);
}
});
// 同时监听失败事件以便处理错误(路径无法解码、解析失败等)
fb2k.on('audio:fullWaveformFailed', (e) => {
if (e.taskId === result.taskId) {
console.error('波形生成失败:', e.error);
}
});
}
// 支持 subsong 格式
const result2 = await fb2k.invoke('audio.generateFullWaveform', {
path: 'E:\\\\Music\\\\disc.flac|subsong:2',
resolution: 512
});
// 使用 cueIndex(优先级高于路径中的 subsong)
const result3 = await fb2k.invoke('audio.generateFullWaveform', {
path: 'E:\\\\Music\\\\album.cue',
cueIndex: 3,
resolution: 256
});
// RMS 模式(更平滑的能量包络)
const result4 = await fb2k.invoke('audio.generateFullWaveform', {
path: 'E:\\\\Music\\\\song.flac',
resolution: 512,
method: 'rms'
});
// signed 模式:输出 [-1, 1] 对称波形(适合绘制上下对称波形图)
const result5 = await fb2k.invoke('audio.generateFullWaveform', {
path: 'E:\\\\Music\\\\song.flac',
resolution: 512,
signed: true
});
// result5.waveform 包含正负值,signed 模式下 scale 参数被忽略采样方法说明:
peak: 取窗口内所有声道绝对值的最大值,适合波形概览和进度条rms: 取窗口内所有声道的均方根值,提供更平滑的能量包络
signed 模式说明:
启用 signed: true 时,波形数据保留 PCM 极性(正/负),归一化到 [-1, 1]:
- 多声道取算术平均(保留符号),窗口内选绝对值最大的采样点(保留符号)
- dB 刻度在 signed 模式下自动忽略(负值取对数无意义)
- 适用于绘制上下对称的波形可视化
- 事件和返回值均包含
"signed": true字段
缓存机制:
- 缓存键包含:路径、subsong、resolution、method、文件大小、修改时间
- 最大缓存条目数:50(LRU 淘汰)
- 文件修改后自动失效
audio.getOutputInfo
获取音频输出信息(当前音量)。
- 参数: 无
返回值:
{ "success": true, "volume": -5.0, "volumePercent": 56.2 }示例:
const info = await fb2k.invoke('audio.getOutputInfo');
console.log(`音量: ${info.volume} dB (${info.volumePercent}%)`);audio.getStreamInfo
获取当前播放流信息(采样率、声道、编码等)。
- 参数: 无
返回值:
{
"success": true,
"playing": true,
"sampleRate": 44100,
"channels": 2,
"bitrate": 1411,
"codec": "FLAC",
"duration": 234.5
}未播放时返回
{ "success": true, "playing": false }。
const info = await fb2k.invoke('audio.getStreamInfo');
if (info.playing) {
console.log(`${info.codec} ${info.sampleRate}Hz ${info.channels}ch`);
}audio.isVisualizationAvailable
检查可视化功能是否可用。
- 参数: 无
- 返回值:
{ "success": true, "available": true }
示例:
const result = await fb2k.invoke('audio.isVisualizationAvailable');
if (result.available) {
console.log('可视化功能可用');
// 可以安全地调用 subscribeSpectrum
await fb2k.invoke('audio.subscribeSpectrum');
}audio.subscribeStream
订阅音频流捕获(用于录音/流媒体)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
event | string | 否 | 可选;默认 audio:stream。 |
interval | number | 否 | 可选;默认 0.05。 |
返回值: {"error":"...","event":"...","interval":"...","success":true}
WARNING
此功能需要 playback_stream_capture 集成,当前未完整实现。
audio.unsubscribeStream
取消音频流捕获。
- 参数: 无
- 返回值:
{ "success": true }
audio.getSpectrumDebugState
获取频谱系统内部调试状态,包含当前订阅列表、分发目标、内部定时器状态等。主要用于诊断频谱订阅问题。
- 参数: 无 返回值:
{"active":true,"callerHwnd":"...","callerOwnsSubscription":"...","callerWindowId":"...","dispatchTargetCount":"...","dispatchTargets":[],"effectiveBands":"...","effectiveFftSize":"...","effectiveFps":"...","foregroundHwnd":"...","foregroundIsExternal":"...","foregroundPid":"...","foregroundTitle":"...","instanceCount":"...","skipFrames":"...","streamReady":"...","subscriptionCount":"...","subscriptions":[],"success":true,"timerHwnd":"...","timerRunning":"..."}
| 字段 | 类型 | 描述 |
|---|---|---|
active | boolean | 频谱系统是否活动 |
timerRunning | boolean | 内部定时器是否运行 |
effectiveFftSize | number | 当前生效的 FFT 大小 |
effectiveFps | number | 当前生效的刷新率 |
effectiveBands | number | 当前生效的频带数 |
streamReady | boolean | 音频流是否就绪 |
subscriptionCount | number | 当前订阅数量 |
subscriptions | array | 订阅详情列表 |
callerOwnsSubscription | boolean | 调用者是否拥有订阅 |
const debug = await fb2k.invoke('audio.getSpectrumDebugState');
console.log(debug.subscriptions);DSP API - 效果器管理
注意:
dsp.getActivePreset/dsp.setActivePreset未在 C++ 层注册,请改用config.getActiveDspPreset/config.setActiveDspPreset。
dsp.getChain
获取当前 DSP 效果器链配置。
- 参数: 无
返回值:
{
"dsps": [
{ "index": 0, "guid": "{...}", "name": "Equalizer" }
],
"activePreset": "My Preset",
"activePresetIndex": 0
}
activePreset与activePresetIndex始终存在,无需判断键是否缺失:当前链不对应任何预设(或宿主不支持预设)时分别为null和-1。手工改链的操作(addDsp/removeDsp/moveDsp/setChain)会使活动链脱离预设,此后这两个字段即为null/-1。
dsp.getPresets
获取所有 DSP 预设列表。
- 参数: 无
返回值:
{
"presets": [
{ "index": 0, "name": "Default", "active": true }
],
"count": 3,
"selectedIndex": 0
}未选中任何预设时
selectedIndex为-1。预设本身持久化在 profile 的dsp-presets\<名称>.fb2k-dsp。
dsp.applyPreset
应用指定的 DSP 预设。通过名称或索引指定。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
index | integer | 否 | 可选;默认 omitted。 |
name | string | 否 | 可选;默认 omitted。 |
name和index至少提供一个;同时提供时index优先。
返回值: { "success": true, "appliedPreset": "My Preset", "appliedIndex": 0 }
// 按名称
await fb2k.invoke('dsp.applyPreset', { name: 'My Preset' });
// 按索引
await fb2k.invoke('dsp.applyPreset', { index: 0 });应用预设会整条替换当前活动链(含各 DSP 的参数),因此它也是把链恢复到某个已知状态的最可靠方式。预设文件本身不会被改写——本接口只写活动链。
dsp.getAvailable
获取所有可用的 DSP 处理器列表(已安装的 DSP 组件)。
- 参数: 无
返回值:
{
"dsps": [
{ "guid": "{...}", "name": "Equalizer", "hasConfig": true }
],
"count": 18
}dsp.addDsp
添加 DSP 效果器到链中。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
guid | string | 是 | 必填。 |
position | integer | 否 | 可选;默认 -1。 |
返回值: { "success": true, "addedDsp": "Equalizer", "position": 2 }
// 获取可用 DSP 列表,然后添加
const available = await fb2k.invoke('dsp.getAvailable');
const eq = available.dsps.find(d => d.name === 'Equalizer');
if (eq) {
await fb2k.invoke('dsp.addDsp', { guid: eq.guid });
}dsp.removeDsp
从链中移除 DSP 效果器。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
index | integer | 是 | 必填。 |
返回值: { "success": true, "removedDsp": "Equalizer", "removedIndex": 2 }
dsp.moveDsp
移动 DSP 效果器在链中的位置。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
from | integer | 是 | 必填。 |
to | integer | 是 | 必填。 |
返回值: {"from":"...","message":"...","movedDsp":"...","success":true,"to":"..."}
from是移动前的下标;to是该项移动后的最终下标,升序、降序都与传入值一致,返回的to即为该值。from === to时不做改动,返回message: "No change needed"。需要重排链请用本接口,不要用setChain(后者只接受guid,不承诺保留参数)。
dsp.setChain
设置完整的 DSP 效果器链(高级用法,替换整个链)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
dsps | array | 是 | 必填。 |
dsps 的每一项必须是含 guid 的对象。任意一项无法解析时整次调用被拒绝且活动链保持不变,错误信息带出错下标:
| 情况 | error |
|---|---|
dsps 缺失或不是数组 | dsps array is required |
| 元素不是对象 | dsps[0] must be an object |
缺 guid、为空串,或不是字符串 | dsps[0]: guid is required |
| GUID 格式非法 | dsps[0]: Invalid GUID format: <值> |
| GUID 合法但该 DSP 未安装 | dsps[0]: DSP not found or no default preset: <值> |
传入空数组是合法的,表示清空整条链,返回 count: 0。
返回值: { "success": true, "count": 3 }
await fb2k.invoke('dsp.setChain', {
dsps: [
{ guid: '{EQ-GUID-HERE}' },
{ guid: '{LIMITER-GUID-HERE}' }
]
});传空数组会清空整条链。本接口只接受
guid,因此每个 DSP 都按其默认预设加入——参数是否得以保留取决于该 DSP 的实现:多数 foobar2000 内置 DSP 把设置存在全局配置里,参数会保留;而按预设实例存参的 DSP(VST 包装器、部分第三方 DSP)会退回出厂值。不要依赖此行为,也不要把getChain的输出直接回灌setChain来做重排序,重排请用dsp.moveDsp。
Output API - 音频输出
output.getDevices
获取所有可用的音频输出设备。
- 参数: 无
返回值:
{
"devices": [
{
"guid": "{...}",
"name": "Speakers (Realtek)",
"entry": "WASAPI (event)",
"entryGuid": "{...}"
}
],
"count": 5
}
guid在本端点内不唯一。 foobar2000 用全零 GUID{00000000-0000-0000-0000-000000000000}表示某个输出模块的「默认设备」,因此多个模块下会各出现一次全零 GUID。 请用(entryGuid, guid)组合作为设备的唯一键,不要只用guid。
output.getEntries
获取输出模块列表(WASAPI, DirectSound 等)。
- 参数: 无
返回值:
{
"entries": [
{
"guid": "{...}",
"name": "WASAPI (event)",
"needsBitdepthConfig": false,
"needsDitherConfig": false,
"supportsMultipleStreams": false,
"isHighLatency": false,
"isLowLatency": true
}
],
"count": 4
}output.getSettings
获取当前输出设置信息(只读)。
- 参数: 无
返回值:
{
"note": "Output settings are managed through foobar2000 Preferences > Playback > Output. availableOutputs lists display names only and cannot disambiguate backends that share a name; use output.getEntries for name + GUID pairs.",
"availableOutputs": ["WASAPI (event)", "WASAPI (push)", "DirectSound", "Primary Sound Driver"]
}实际输出设置通过 foobar2000 首选项管理。如需切换输出设备,请使用
config.setOutputDevice。
不建议在新代码中使用
availableOutputs。 它只是一个显示名数组,存在两个已实测的问题: 同名模块无法区分(多个后端都叫「默认」),以及某些模块的名称为空字符串。 此外该数组的顺序来自服务枚举,多次调用之间并不稳定,因此不能依赖数组下标定位模块。 需要可编程地识别输出模块时请改用output.getEntries,它为每个名称附带 GUID。
ReplayGain API
ReplayGain 音量标准化设置。
replaygain.getSettings
获取所有 ReplayGain 设置。
- 参数: 无
返回值:
{
"sourceMode": "track",
"processingMode": "gain",
"preampWithRg": 0.0,
"preampWithoutRg": 0.0,
"active": true
}| 字段 | 类型 | 描述 |
|---|---|---|
sourceMode | string | 音源模式 |
processingMode | string | "none" / "gain" / "gain_and_peak" / "peak" |
preampWithRg | number | 有 RG 时的预增益 (dB) |
preampWithoutRg | number | 无 RG 信息时的预增益 (dB) |
active | boolean | RG 是否激活 |
replaygain.getMode
获取当前 ReplayGain 模式。
- 参数: 无
- 返回值:
{ "sourceMode": "track", "processingMode": "gain" }
replaygain.setMode
设置 ReplayGain 模式。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
processingMode | string | 否 | 可选;默认 omitted。 |
sourceMode | string | 否 | 可选;默认 omitted。 |
返回值: { "success": true, "sourceMode": "track", "processingMode": "gain", "changed": true }
await fb2k.invoke('replaygain.setMode', { sourceMode: 'album', processingMode: 'gain' });replaygain.getPreamp
获取预增益设置。
- 参数: 无
返回值:
{ "withRg": 0.0, "withoutRg": 0.0 }| 字段 | 类型 | 描述 |
|---|---|---|
withRg | number | 有 RG 时的预增益 (dB) |
withoutRg | number | 无 RG 信息时的预增益 (dB) |
replaygain.setPreamp
设置预增益值。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
withoutRg | number | 否 | 可选;默认 omitted。 |
withRg | number | 否 | 可选;默认 omitted。 |
返回值: { "success": true, "withRg": 3.0, "withoutRg": 0.0, "changed": true }
await fb2k.invoke('replaygain.setPreamp', { withRg: 3.0, withoutRg: -3.0 });replaygain.get
获取指定文件的 ReplayGain 信息。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
paths | array | 是 | 必填。 |
返回值:
{
"success": true,
"count": 1,
"results": [
{
"path": "C:\\\\Music\\\\song.flac",
"success": true,
"trackGain": "-5.20 dB",
"trackGainRaw": -5.2,
"trackPeak": "0.987654",
"trackPeakRaw": 0.987654,
"albumGain": "-4.80 dB",
"albumGainRaw": -4.8,
"albumPeak": "1.000000",
"albumPeakRaw": 1.0,
"hasReplayGain": true
}
]
}缺少 RG 信息的字段不会出现在结果中。
hasReplayGain表示是否有任何 track 或 album gain 数据。
replaygain.clear
移除文件中的 ReplayGain 信息。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
paths | array | 是 | 必填。 |
返回值: { "success": true, "clearedCount": 5 }
replaygain.scan
扫描文件的 ReplayGain(通过右键菜单触发,扫描结果自动写入文件)。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
mode | string | 否 | 可选;默认 track。 |
paths | array | 是 | 必填。 |
返回值: { "success": true, "scannedCount": 10, "mode": "track", "note": "Scan started. Results will be written to files automatically." }
// 扫描单曲 track gain
await fb2k.invoke('replaygain.scan', {
paths: ['C:\\\\Music\\\\song.flac'],
mode: 'track'
});
// 扫描整张专辑
await fb2k.invoke('replaygain.scan', {
paths: ['C:\\\\Music\\\\01.flac', 'C:\\\\Music\\\\02.flac'],
mode: 'album'
});运行时行为说明
audio.subscribeSpectrum会创建或更新由调用方拥有的订阅。省略subscriptionId时,runtime 使用按调用方作用域生成的 legacy 标识;监听配置的event,默认值为audio:spectrum。audio.getSpectrum与audio.getWaveform读取可视化流。在存在频谱订阅且有可用音频数据前,它们会返回错误。audio.generateWaveform当前会返回文件元数据以及“尚未实现基于解码器的波形生成”的失败结果。异步且带缓存的流程应使用audio.generateFullWaveform。audio.generateFullWaveform命中缓存时返回带数据的status: "ready",否则返回带taskId的status: "pending"。调用方会收到audio:fullWaveformReady或audio:fullWaveformFailed;非负的cueIndex优先于path|subsong:N后缀。audio.subscribeStream是能力 stub:在集成playback_stream_capture前始终返回success: false。调用audio.unsubscribeStream仍然安全。- 每个构建都会注册 DSP 方法。若 foobar2000 DSP SDK 表面不可用,全部
dsp.*方法都会返回 runtime 的 "DSP API not available in this build" 失败,不会模拟 DSP 链。 output.getSettings仅提供只读发现信息。输出配置由 foobar2000 Preferences 管理,而非本 API。replaygain.get读取每个传入媒体路径;replaygain.clear通过 foobar2000 异步写入 ReplayGain 元数据。replaygain.scan请求 host 扫描器,并非同步分析结果。
合同补充
以下章节补齐严格参数审计发现的公开 contract;不会改变前文的已有说明。
Contract 补充:audio.subscribeSpectrum
经复核的补充 contract。权威源:src/api/AudioApi.cpp:719-762。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
subscriptionId | string | 否 | `` | 可选;默认 。 |
fftSize | integer | 否 | 1024 | 可选;默认 1024。 |
event | string | 否 | audio:spectrum | 可选;默认 audio:spectrum。 |
fps | integer | 否 | 30 | 可选;默认 30。 |
bands | integer | 否 | 48 | 可选;默认 48。 |
返回字段
| 字段 | 类型 | 可选 |
|---|---|---|
error | string | 是 |
success | boolean | 否 |
bands | json | 否 |
event | json | 否 |
fftSize | json | 否 |
fps | json | 否 |
subscriptionId | json | 否 |
语义:省略可选参数时使用 handler 默认值;失败分支及错误字段以该源文件为准。
const result = await fb2k.invoke('audio.subscribeSpectrum', { subscriptionId: /* value */, fftSize: /* value */, event: /* value */, fps: /* value */, bands: /* value */ });