fix(playback): 位置回退保护 + 恢复用最后已知位置 + 缓冲感知重试
对应 10/24 日志里的"播到一半中断后从头重播": 23:05:26 ffurl_read -> 从 77s 重连成功 23:05:33 再断 -> position 归 0 -> 看门狗"从 0s 继续",听感就是重新开始 - 新增 _lastKnownPosition:位置流累积,切歌归零; 所有恢复路径(看门狗 / 网络切换 / 打开失败)都用它续播 - 位置回退保护(抽成 utils/position_guard.dart): 已播 >10s 且新位置 <5s 时忽略回退,除非用户 seek / 切歌 / 正在恢复 - _scheduleOpenRetry 改为缓冲感知: 缓冲余量 >=12s 时延迟 4s 重试(不打断),否则 1.2s; 重试前若位置已推进超过 1s,判定 mpv 自愈,取消重连 - 收藏列表点击改为整队入队(setQueue,从点击项开始) 测试:新增 position_guard 6 个用例,累计 25 个全绿。 真机验证:收藏整队日志 "17 首,从第 16 首开始",播放正常。
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
// test/position_guard_test.dart
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:qingting_player/utils/position_guard.dart';
|
||||
|
||||
void main() {
|
||||
group('shouldIgnorePositionRegression', () {
|
||||
test('正常播放推进:不拦截', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 77),
|
||||
incoming: const Duration(seconds: 78),
|
||||
isChangingTrack: false,
|
||||
isRecovering: false,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('77s 突然归零:拦截(这就是"从头重播"的元凶)', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 77),
|
||||
incoming: Duration.zero,
|
||||
isChangingTrack: false,
|
||||
isRecovering: false,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('用户切歌:允许回退', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 200),
|
||||
incoming: Duration.zero,
|
||||
isChangingTrack: true,
|
||||
isRecovering: false,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('自动恢复中:允许回退(我们自己重开的)', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 200),
|
||||
incoming: Duration.zero,
|
||||
isChangingTrack: false,
|
||||
isRecovering: true,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('刚开始播放(最后位置 <10s):不拦截,避免误伤起播', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 8),
|
||||
incoming: Duration.zero,
|
||||
isChangingTrack: false,
|
||||
isRecovering: false,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('小幅回退(77s -> 73s):不拦截', () {
|
||||
expect(
|
||||
shouldIgnorePositionRegression(
|
||||
lastKnown: const Duration(seconds: 77),
|
||||
incoming: const Duration(seconds: 73),
|
||||
isChangingTrack: false,
|
||||
isRecovering: false,
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user