playScene method
Implementation
Future<void> playScene(
Scene scene,
String streamUrl, {
String? mimeType,
String? streamLabel,
String? streamSource,
Map<String, String>? httpHeaders,
bool? prewarmAttempted,
bool? prewarmSucceeded,
int? prewarmLatencyMs,
}) async {
final allowBackgroundPlayback = state.enableBackgroundPlayback;
AppLogStore.instance.add(
'provider playScene begin scene=${scene.id} source=${streamSource ?? '-'} mime=${mimeType ?? '-'}',
source: 'player_provider',
);
if (state.activeScene?.id == scene.id &&
state.videoPlayerController != null) {
_videoControllerRef ??= state.videoPlayerController;
state.videoPlayerController?.play();
AppLogStore.instance.add(
'provider playScene replay-active scene=${scene.id}',
source: 'player_provider',
);
state = state.copyWith(
isPlaying: true,
streamMimeType: mimeType,
streamLabel: streamLabel,
streamSource: streamSource,
prewarmAttempted: prewarmAttempted,
prewarmSucceeded: prewarmSucceeded,
prewarmLatencyMs: prewarmLatencyMs,
);
return;
}
// Detach the currently rendered player widget before disposing native players.
if (state.activeScene != null) {
state = state.copyWith(clearActive: true, isPlaying: false);
}
// Stop current
await _disposeControllers();
if (!ref.mounted) return;
final stopwatch = Stopwatch()..start();
final videoController = VideoPlayerController.networkUrl(
Uri.parse(streamUrl),
httpHeaders: httpHeaders ?? const <String, String>{},
videoPlayerOptions: VideoPlayerOptions(
allowBackgroundPlayback: allowBackgroundPlayback,
),
);
_videoControllerRef = videoController;
_firstFrameLoggedSceneId = null;
state = state.copyWith(
activeScene: scene,
videoPlayerController: videoController,
isPlaying: false,
streamMimeType: mimeType,
streamLabel: streamLabel,
streamSource: streamSource,
startupLatencyMs: null,
prewarmAttempted: prewarmAttempted,
prewarmSucceeded: prewarmSucceeded,
prewarmLatencyMs: prewarmLatencyMs,
);
try {
await videoController.initialize();
if (!ref.mounted) {
await _disposeControllers();
return;
}
stopwatch.stop();
final initializeElapsedMs = stopwatch.elapsedMilliseconds;
AppLogStore.instance.add(
'provider initialize done scene=${scene.id} elapsed=${initializeElapsedMs}ms duration=${videoController.value.duration.inMilliseconds}ms size=${videoController.value.size.width.toStringAsFixed(0)}x${videoController.value.size.height.toStringAsFixed(0)}',
source: 'player_provider',
);
state = state.copyWith(
isPlaying: true,
startupLatencyMs: initializeElapsedMs,
);
mediaHandler?.updateMetadata(
id: scene.id,
title: scene.title,
studio: scene.studioName,
thumbnailUri: scene.paths.screenshot,
duration: videoController.value.duration,
);
AppLogStore.instance.add(
'provider ready scene=${scene.id} startup=${initializeElapsedMs}ms',
source: 'player_provider',
);
unawaited(WakelockPlus.enable());
videoController.addListener(_videoListener);
unawaited(videoController.play());
} catch (e) {
debugPrint('Error initializing video player: $e');
AppLogStore.instance.add(
'provider initialize error scene=${scene.id} error=$e',
source: 'player_provider',
);
if (ref.mounted) {
stop();
} else {
await _disposeControllers();
}
}
}