fix(player): 预解码观看全集首帧
This commit is contained in:
1 parent
1fc8c4924e
commit
c8ec481fc9
5 files changed
+145
-26
No files matched your search
@@ -6,11 +6,56 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
import '../../core/config/app_config.dart';
|
||||
|
||||
class PreparedPlayerFrame {
|
||||
const PreparedPlayerFrame({this.bytes, this.provider});
|
||||
|
||||
final Uint8List? bytes;
|
||||
final ImageProvider<Object>? provider;
|
||||
|
||||
bool get isReady => bytes != null || provider != null;
|
||||
}
|
||||
|
||||
class PlayerFrameCapture {
|
||||
const PlayerFrameCapture._();
|
||||
|
||||
static const int budgetMilliseconds = 32;
|
||||
|
||||
static Future<PreparedPlayerFrame> captureAndPrecache({
|
||||
required BuildContext context,
|
||||
required GlobalKey boundaryKey,
|
||||
required String source,
|
||||
String? fallbackPosterUrl,
|
||||
}) async {
|
||||
final bytes = await capture(
|
||||
context: context,
|
||||
boundaryKey: boundaryKey,
|
||||
source: source,
|
||||
);
|
||||
if (bytes != null) {
|
||||
if (!context.mounted) return const PreparedPlayerFrame();
|
||||
final provider = MemoryImage(bytes);
|
||||
if (await _precache(context, provider, source: source, kind: 'capture')) {
|
||||
_log(
|
||||
'[player-entry] phase=frame-precached source=$source kind=capture',
|
||||
);
|
||||
return PreparedPlayerFrame(bytes: bytes, provider: provider);
|
||||
}
|
||||
}
|
||||
|
||||
final poster = fallbackPosterUrl?.trim() ?? '';
|
||||
if (poster.isNotEmpty) {
|
||||
if (!context.mounted) return const PreparedPlayerFrame();
|
||||
final provider = NetworkImage(AppConfig.mediaUrl(poster));
|
||||
if (await _precache(context, provider, source: source, kind: 'poster')) {
|
||||
_log('[player-entry] phase=frame-precached source=$source kind=poster');
|
||||
return PreparedPlayerFrame(provider: provider);
|
||||
}
|
||||
}
|
||||
return const PreparedPlayerFrame();
|
||||
}
|
||||
|
||||
static Future<Uint8List?> capture({
|
||||
required BuildContext context,
|
||||
required GlobalKey boundaryKey,
|
||||
@@ -57,6 +102,32 @@ class PlayerFrameCapture {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<bool> _precache(
|
||||
BuildContext context,
|
||||
ImageProvider<Object> provider, {
|
||||
required String source,
|
||||
required String kind,
|
||||
}) async {
|
||||
var failed = false;
|
||||
try {
|
||||
await precacheImage(
|
||||
provider,
|
||||
context,
|
||||
onError: (_, _) {
|
||||
failed = true;
|
||||
},
|
||||
);
|
||||
} catch (_) {
|
||||
failed = true;
|
||||
}
|
||||
if (failed) {
|
||||
_log(
|
||||
'[player-entry] phase=frame-precache-failed source=$source kind=$kind',
|
||||
);
|
||||
}
|
||||
return !failed;
|
||||
}
|
||||
|
||||
static void _log(String message) {
|
||||
if (kDebugMode) debugPrint(message);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user