fix(player): 修复播放失败死循环,失败静默重试一次后直接跳下一首

日志实证的故障链:试听歌曲走备用解析 → 命中缓存的失效 URL → Format
error → url_expired → 原样重放 → 再次命中同一坏缓存(30 分钟 TTL 内
永远命中)→ 死循环,最终静默停止且不切歌。

修复:
- url_expired 恢复前清除该歌曲的解析 URL 缓存(clearMusicCache 此前
  只有手动重新解析按钮调用),重试真正拿到新 URL
- 恢复为静默重试且仅 1 次(无任何用户提示),仍失败直接切下一首
  (单曲列表停止/FM 拉新歌),playTrack 成功时重置计数
- 恢复前校验当前歌曲未变更,避免与 nextPlay 的失败跳歌并发争抢
- nextPlay 播放失败不再原地重试,直接静默跳过下一首
- 修复连续失败上限从未生效的存量 bug:跳歌链递归重置了
  consecutiveFailCount,全列表失效时会无限跳歌;现失败链不重置计数,
  连续 5 次失败正确停止
- audioService 对 MEDIA_ERR_SRC_NOT_SUPPORTED(4) 不再用同一 URL 重试
  (源本身无效,重试纯耗时),网络类错误保留原重试

测试:16 项全过——恢复状态机 8 场景、错误分类 2 项、真实 HTTP 服务
集成 2 项(坏缓存死循环复现 + 清缓存换新 URL 恢复)、跳歌链 4 场景
(直接跳过/全失败恰好 5 次后停止/旧计数重置 bug 复现/主动切歌重置)。
This commit is contained in:
alger
2026-07-05 16:39:40 +08:00
parent 968116ce18
commit 960afd04be
3 changed files with 110 additions and 55 deletions
+5 -1
View File
@@ -484,7 +484,11 @@ class AudioService {
console.error('Audio load error:', error?.code, error?.message);
this.emit('loaderror', { track, error });
if (retryCount < maxRetries) {
// MEDIA_ERR_SRC_NOT_SUPPORTED(4):源本身无效(URL 已失效/返回了
// 非音频内容),用同一 URL 重试毫无意义,直接走 url_expired 换新 URL
const isSrcNotSupported = error?.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED;
if (!isSrcNotSupported && retryCount < maxRetries) {
retryCount++;
console.log(`Retrying playback (${retryCount}/${maxRetries})...`);
setTimeout(tryPlay, 1000 * retryCount);