Skip to content

feat(player): 实现自动混音与下一首预加载#70

Open
laoshuikaixue wants to merge 16 commits into
SPlayer-Dev:devfrom
laoshuikaixue:feature/automix-crossfade-dual-slot
Open

feat(player): 实现自动混音与下一首预加载#70
laoshuikaixue wants to merge 16 commits into
SPlayer-Dev:devfrom
laoshuikaixue:feature/automix-crossfade-dual-slot

Conversation

@laoshuikaixue

@laoshuikaixue laoshuikaixue commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

为SPlayer-Next实现自动混音(Automix)功能,在无需手动操作的情况下通过双槽预载、音频分析与交叉淡化,让歌曲之间平滑过渡。

功能概览

  • 曲末自动检测下一首并静默预载(提前约 45 秒)
  • 对本地音频文件进行内容分析,识别静音边界、BPM、人声位置、Drop与调性
  • 根据分析结果自动选择最合适的过渡策略并执行双槽 Crossfade
  • 支持 Bass Swap(过渡期间动态高通交换低频)
  • 用户可在设置中启用/禁用,并可调整最大分析时长

Native层(Rust)

audio-engine:

  • 新增 PreparedTrack / commit_crossfade 双槽架构,原播放器在旧槽渐出期间不停止,新槽在后台渐入
  • crossfade_volume:Equal-power(cos/sin)曲线,每秒约 100 次更新,替代原来固定 20 步线性阶梯
  • analysis.rs:TrackAnalyzer 分析 silence、BPM(归一化自相关+低频辅助、真实 confidence)、Key(Krumhansl-Schmuckler chroma、真实 confidence)、Drop、Vocal、能量包络、LUFS
  • analysis.rs:新增 analyze_pair NAPI 函数,单次打开每个文件同时返回两轨分析结果与过渡建议,替代原来4次独立解码
  • shared.rsHighPassAutomation 实现 Bass Swap 高通包络(截止频率约 150Hz);cutoff_at 返回 Option<f32>,FadeIn 完成后自动清除
  • source.rsDecoderSource 改为按实际输出帧推进samples_consumed,输出时钟更贴近真实播放位置
  • lib.rsJsCrossfadeOptions 新增 loudness_gain_db 字段,支持过渡区短时响度补偿

分析正确性修复:

  • Key FFT 滑窗步长从 chunks(4096).step_by(1024) 改为正确的逐帧索引步进
  • Duration 优先使用 metadata 估算值,并以解码包终点持续更新
  • ANALYSIS_VERSION 升至 14,使旧缓存失效

渲染层(TypeScript)

src/core/player/automix.ts:

  • tickAutomix:由 position 事件驱动,无额外 IPC;首次进入 45 秒窗口立即后台触发 kickPairAnalysis(fire-and-forget),不阻塞 handler;分析未完成时最多等到 PLAN_DEADLINE_MS,超时后冻结为安全兜底
  • computePlan:依次尝试 TransitionProposal(结构感知)→本地分析兜底,统一经normalizePlan 校验边界
  • BPM/调性真实 confidence 门控(MIN_BEAT_CONFIDENCE = 0.65),低置信度自动降为普通 Equal-power Crossfade
  • computeLoudnessGainDb:利用 LUFS 分析结果计算 ±6dB 响度补偿
  • CUE 分轨自动排除(当前/下一首含 cuePath 时不进入automix)
  • transitioning 使用 try/finally 保证异常时正确复位;分析 Promise有catch 与 deadline,不会无限挂起
  • cancelAutomix 状态机从 7 变量精简为 5 变量

src/core/player/preload.ts:

  • preloadNextTrack 保持独立,automix 启用时同步触发

electron/preload/index.ts + electron/main/ipc/player.ts:

  • 新增 analyzePairsuggestTransitionsuggestLongMixcrossfadeTo 等 IPC 接口及 Worker 路由

shared/types/player.ts:

  • 新增 AutomixPlanPairAnalysisResultCrossfadeOptions(含 loudnessGainDbuiSwitchDelayMs 等)类型

将旧版 SPlayer 的 Automix 能力完整迁移到 SPlayer-Next,同时首次支持歌曲预加载。新实现基于 Rust audio-engine 双槽架构(当前槽 + bounded preload 槽),不影响现有普通播放路径。

变更内容:
- native/audio-engine 双槽播放:新增 preload/cancelPreload/crossfadeTo NAPI,preload 保留一个 bounded prepared slot,crossfadeTo 优先复用匹配预载槽。过渡期间旧槽淡出、新槽淡入,完成后释放旧槽资源。
- 迁移旧版音频分析(analysis.rs):BPM/调性/Smart Cut/transition proposal 到 native,通过主进程 worker 暴露 analyzeAudioFile、analyzeAudioFileHead、suggestTransition、suggestLongMix,避免阻塞主线程。分析结果作有界缓存,切歌/队列变化立即失效。
- 渲染层预载编排(preload.ts):根据队列、播放模式、音质解析下一首 URL,优先命中本地缓存;未命中时立即 preload 真实 URL,后台触发缓存下载。
- 渲染层 Automix 调度(automix.ts):复用旧版计划计算,输出 trigger time、crossfade duration、next start seek、initial rate、mix type,position 事件驱动,不新增高频 IPC。
- 中点 UI 提交(transitionCommit):主进程在 crossfade 中点统一提交 UI/歌词/封面/媒体状态/历史记录/预载。过渡期间忽略 native 新槽提前的 position/status,旧曲 UI 持续到 commit 点再切换。
- bassSwap 滤波:native 二阶 biquad 高通包络,旧曲前半段拉到 400Hz、新曲在 crossfade 中点释放回直通,贴合旧版 DJ 互换听感。
- 设置项:preloadNext(默认 true)、automixEnabled(默认 false)、automixMaxAnalyzeTimeSec(默认 60,范围 10-300),补充中英文 i18n 与播放设置项。
- 添加了 default 分支处理未知状态情况
- 返回空字符串避免 undefined 值导致的显示问题
- 确保函数在所有情况下都有明确的返回值
- 修正了 en-US.json 中 showLyricInBar 配置项后的多余逗号
- 修正了 zh-CN.json 中 showLyricInBar 配置项后的多余逗号
- 确保 JSON 文件格式正确性
@laoshuikaixue laoshuikaixue marked this pull request as draft July 10, 2026 04:11
- 将音频分析版本从13升级到14以支持新的分析特性
- 重构BPM检测算法,增加低频环境相关性计算和置信度评估
- 改进关键检测逻辑,使用更精确的分数排序和置信度计算
- 优化音频处理流程中的持续时间跟踪机制
- 调整混音参数限制,包括最大交叉淡入淡出时间和节拍置信度阈值
- 增强音频引擎中的渐变步数计算,支持动态步长调整
- 实现音频时钟同步机制,确保变速播放的时间准确性
- 添加分析超时控制和错误处理机制
- 优化过渡计划验证,增加对节拍网格可靠性的检查
- 实现 computeLoudnessGainDb 函数计算新旧歌曲间的响度差异
- 在 AutomixPlan 中加入 loudnessGainDb 字段传递响度补偿值
- 扩展 AudioOptions 类型定义支持响度补偿参数
- 在音频引擎中接收并应用响度补偿值调整目标音量
- 更新 BassSwap 算法中高通滤波器的截止频率参数
- 优化高通滤波自动化逻辑并在完成后清理相关资源
- 将原有的四次独立分析请求合并为单次双曲分析
- 减少文件IO操作,提升分析效率
- 引入PairAnalysisResult结构统一管理双曲分析结果
- 移除过时的单独过渡建议和长段混音建议函数
- 重构自动化混音逻辑以适配新的分析接口
- 删除 PairAnalysisResult 类型引用
- 移除高级过渡相关代码块和计算逻辑
- 简化过渡策略判断条件
- 优化自动混音计划生成流程
- 清理无用的过渡参数和变量声明
- 统一混音策略处理方式
- 从类型导入中删除 AdvancedTransition 类型
- 从模块作用域变量中移除 advancedTransition 变量
- 在清理函数中移除对 advancedTransition 的重置操作
- 从分析数据处理中移除 long_mix 数据赋值逻辑
- 将多行类型导入合并为单行导入语句
- 移除不必要的换行和空格
- 统一导入语句的代码风格
- 在BPM计算中添加非空断言操作符以避免类型检查错误
- 确保当前曲目和下一曲目的BPM值都被正确处理
- 保持原有的节拍网格检测和速率调整逻辑不变
@laoshuikaixue laoshuikaixue changed the title feat(player): 迁移自动混音与下一首预加载,实现完整双槽 crossfade feat(player): 实现自动混音与下一首预加载 Jul 10, 2026
…ade-dual-slot

# Conflicts:
#	native/audio-engine/src/source.rs
@laoshuikaixue laoshuikaixue marked this pull request as ready for review July 10, 2026 06:53
@laoshuikaixue

Copy link
Copy Markdown
Contributor Author

Ready @imsyy

@laoshuikaixue

Copy link
Copy Markdown
Contributor Author
2026-07-10.14-57-00.mp4

@imsyy imsyy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

合并阻断

audio-engine 当前编译失败

验证命令:

cargo check -p audio-engine

结果:失败。

核心错误:

native/audio-engine/src/lib.rs:457:25
expected Result<JoinHandle<DecoderData>, Error>, found JoinHandle<DecoderData>

native/audio-engine/src/lib.rs:435:17
cannot infer type

native/audio-engine/src/decoder.rs:171:19
expected JoinHandle<DecoderData>, found Result<JoinHandle<DecoderData>, Error>

- 在 decoder.rs 中为 resume_decode 调用添加错误传播操作符
- 在 lib.rs 中为 resume_decode 调用添加 into_napi 错误转换
- 修复 SideBar.vue 中路由跳转的代码格式问题
@laoshuikaixue laoshuikaixue requested a review from imsyy July 10, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants