fix(playback): 自动恢复熔断,避免坏文件导致无限重试
日志证据(21:32~21:33):同一首 "Communications - Keeno" Failed to open ×42,自动恢复 ×54 —— 看门狗每 10s 重开一次,死循环。 - 新增 _recoveryAttempts:同一首歌最多自动恢复 3 次 - 起播看门狗、网络切换、打开失败重试都受熔断约束 - 位置 >1s(真的出声)后清零,正常歌曲不受影响 - 切歌清零,用户手动点播放可重新尝试 - 熔断后写入 lastPlaybackError="无法播放:<title>" 并停住,不再刷请求 测试 25 个全绿;release 已安装。
This commit is contained in:
@@ -113,6 +113,12 @@ class AudioService extends ChangeNotifier {
|
||||
/// 正在执行自动恢复(此时允许位置回退,因为是我们自己重开的)
|
||||
bool _isRecovering = false;
|
||||
|
||||
/// 当前这首歌已经连续自动恢复了几次(成功后清零)。
|
||||
/// 打开一首本身拿不到数据的歌时,看门狗会无限重试,
|
||||
/// 必须熔断,否则日志和请求都会爆炸。
|
||||
int _recoveryAttempts = 0;
|
||||
static const int _maxRecoveryAttempts = 3;
|
||||
|
||||
/// 当前歌曲开始加载的时间,用于"起播看门狗":
|
||||
/// 有些情况下 mpv 的 playing 已经是 true,但 position 永远是 0、
|
||||
/// 也不发 buffering / error(实测公网链路可静默卡 75s+)。
|
||||
@@ -324,6 +330,7 @@ class AudioService extends ChangeNotifier {
|
||||
_hasStartedCurrentPlayback = false;
|
||||
// 切歌:位置基准归零,避免上一首的最后位置被当成这一首的"最后已知位置"
|
||||
_lastKnownPosition = Duration.zero;
|
||||
_recoveryAttempts = 0;
|
||||
|
||||
try {
|
||||
_playbackGeneration++;
|
||||
@@ -606,6 +613,17 @@ class AudioService extends ChangeNotifier {
|
||||
final url = song.url;
|
||||
if (url == null || url.isEmpty) return;
|
||||
|
||||
// 熔断:同一首歌连续恢复失败,说明不是"卡了一下",
|
||||
// 而是这个文件/连接根本拿不到数据。继续重试只会刷日志、抢带宽。
|
||||
if (_recoveryAttempts >= _maxRecoveryAttempts) {
|
||||
debugPrint('⛔ [AudioService] 已连续恢复 $_recoveryAttempts 次仍无法播放,'
|
||||
'停止自动重试:${song.title}');
|
||||
_lastPlaybackError = '无法播放:${song.title}';
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
_recoveryAttempts++;
|
||||
|
||||
final now = DateTime.now();
|
||||
if (!force &&
|
||||
_lastStallRecoveryAt != null &&
|
||||
@@ -1030,6 +1048,11 @@ class AudioService extends ChangeNotifier {
|
||||
_lastKnownPosition = position;
|
||||
}
|
||||
|
||||
// 真的出声了(>1s),说明恢复成功,重置熔断计数
|
||||
if (position > const Duration(seconds: 1)) {
|
||||
_recoveryAttempts = 0;
|
||||
}
|
||||
|
||||
// 首次拿到 >0 的播放位置:这是"真正出声"的时刻,
|
||||
// 与 play() 发起时间相减即可算出起播延迟。
|
||||
if (!_firstAudioReported && position > Duration.zero) {
|
||||
|
||||
Reference in New Issue
Block a user