fix(playback): 修复切歌永久假死,并让元数据抓取不再抢播放带宽
问题(后台播一段时间后无法缓冲,点下一首也没反应,只能重启):
1. _isChangingTrack 是没有超时的锁:_playCurrent() 置 true 后,
只有走完 finally 才会清。mpv 的 open() 在弱网下可能挂很久,
锁就一直不释放,之后 next()/previous() 全被静默拒绝。
2. 元数据用 dio.download 整文件下载,和 mpv 流式播放抢带宽,
20Mbps FRP 下播放流只剩一两百 K/s,缓冲长期为 0。
3. 没有订阅 mpv 的 error/buffering,失败无感知、无法自愈。
改动:
- playback_service: open 20s / 控制命令 5s 超时;失败时 stop 回空闲并上抛异常
- audio_service:
* 去掉「正在切歌就拒绝」的逻辑,改为 latest-wins(epoch 校验,
旧请求自行放弃,只有最新请求解锁)
* 播放失败不再吞掉:记录 lastPlaybackError 并 notifyListeners
* 订阅 stream.error / stream.buffering
* 缓冲超过 30s 自动重连当前歌曲并 seek 回原位置(2 分钟内最多一次)
- file_provider: 元数据改为 Range 只取头部 2MB,流式写入并在切歌时取消上一请求
- home_page: 去掉重复的 PlaybackService().play()(同一首歌会被 open 两次),
登录校验提前
验证:dart analyze 无 error;gradlew assembleDebug BUILD SUCCESSFUL。
真机验证待设备重新连接后进行。
This commit is contained in:
+14
-12
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../services/audio_service.dart';
|
||||
import '../services/webdav_service.dart';
|
||||
import '../services/playback_service.dart';
|
||||
import '../widgets/magnetic_scroll_physics.dart';
|
||||
import 'webdav_setup_page.dart';
|
||||
import 'webdav_file_list_page.dart';
|
||||
@@ -246,16 +245,10 @@ class _HomePageState extends BaseState<HomePage> {
|
||||
|
||||
void _playSong(SongItem song) async {
|
||||
try {
|
||||
final url = WebDAVService.instance.getFileUrl(song.path);
|
||||
|
||||
final audioService = context.read<AudioService>();
|
||||
audioService.playSong(Song(
|
||||
id: song.path,
|
||||
title: song.displayTitle,
|
||||
artist: song.displaySubtitle,
|
||||
url: url,
|
||||
));
|
||||
|
||||
// 先校验登录,再开始播放。
|
||||
// 以前这里是:playSong() 不 await,紧跟着又 PlaybackService().play() 一次,
|
||||
// 同一个 Player 会被 open 两次,media_kit 串行化时第二次会顶掉第一次,
|
||||
// 表现就是"媒体加载了但没有声音"。
|
||||
final headers = await WebDAVService.instance.getAuthHeaders();
|
||||
|
||||
if (headers.isEmpty) {
|
||||
@@ -270,7 +263,16 @@ class _HomePageState extends BaseState<HomePage> {
|
||||
return;
|
||||
}
|
||||
|
||||
await PlaybackService().play(url, headers: headers);
|
||||
if (!mounted) return;
|
||||
|
||||
final url = WebDAVService.instance.getFileUrl(song.path);
|
||||
final audioService = context.read<AudioService>();
|
||||
await audioService.playSong(Song(
|
||||
id: song.path,
|
||||
title: song.displayTitle,
|
||||
artist: song.displaySubtitle,
|
||||
url: url,
|
||||
));
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
|
||||
Reference in New Issue
Block a user