Fix BIF scrub preview aspect ratio and raise desktop size limit
This commit is contained in:
@@ -25,6 +25,9 @@ class MediaSourceInfo {
|
||||
/// null here and uses [partId] + the BIF service instead.
|
||||
final Map<int, TrickplayInfo>? trickplayByWidth;
|
||||
|
||||
/// Display aspect ratio of the video stream (width / height).
|
||||
final double? videoAspectRatio;
|
||||
|
||||
MediaSourceInfo({
|
||||
required this.videoUrl,
|
||||
required this.audioTracks,
|
||||
@@ -36,6 +39,7 @@ class MediaSourceInfo {
|
||||
this.defaultAudioStreamIndex,
|
||||
this.defaultSubtitleStreamIndex,
|
||||
this.trickplayByWidth,
|
||||
this.videoAspectRatio,
|
||||
});
|
||||
int? getPartId() => partId;
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'dart:typed_data';
|
||||
import 'plex_client.dart';
|
||||
import 'scrub_preview_source.dart';
|
||||
import '../utils/app_logger.dart';
|
||||
import '../utils/platform_detector.dart';
|
||||
|
||||
/// A single BIF thumbnail entry: timestamp in milliseconds + JPEG bytes.
|
||||
typedef BifEntry = ({int timestampMs, Uint8List imageBytes});
|
||||
@@ -66,14 +67,20 @@ List<BifEntry> _parseBifBytes(Uint8List bytes) {
|
||||
class BifThumbnailService implements ScrubPreviewSource {
|
||||
List<BifEntry>? _entries;
|
||||
|
||||
double? _aspectRatio;
|
||||
|
||||
/// Download and parse the BIF file for [partId].
|
||||
/// Returns silently on failure (thumbnails simply won't be available).
|
||||
Future<void> load(PlexClient client, int partId) async {
|
||||
Future<void> load(PlexClient client, int partId, {double? aspectRatio}) async {
|
||||
_aspectRatio = aspectRatio;
|
||||
_entries = null;
|
||||
try {
|
||||
final bytes = await client.downloadBifFile(partId);
|
||||
if (bytes == null || bytes.isEmpty) return;
|
||||
if (bytes.length > 50 * 1024 * 1024) {
|
||||
const fiftyMb = 50 * 1024 * 1024;
|
||||
const twoHundredMb = 200 * 1024 * 1024;
|
||||
final maxBytes = PlatformDetector.isDesktopOS() ? twoHundredMb : fiftyMb;
|
||||
if (bytes.length > maxBytes) {
|
||||
appLogger.w('BIF file too large (${bytes.length} bytes), skipping');
|
||||
return;
|
||||
}
|
||||
@@ -91,7 +98,7 @@ class BifThumbnailService implements ScrubPreviewSource {
|
||||
ScrubFrame? getFrame(Duration time) {
|
||||
final bytes = getThumbnail(time);
|
||||
if (bytes == null) return null;
|
||||
return BytesScrubFrame(bytes);
|
||||
return BytesScrubFrame(bytes, aspectRatio: _aspectRatio ?? 16 / 9);
|
||||
}
|
||||
|
||||
/// Return the JPEG bytes for the thumbnail nearest to [time].
|
||||
|
||||
@@ -3505,7 +3505,7 @@ class PlexClient
|
||||
if (partId == null) return null;
|
||||
final service = BifThumbnailService();
|
||||
try {
|
||||
await service.load(this, partId);
|
||||
await service.load(this, partId, aspectRatio: mediaSource.videoAspectRatio);
|
||||
return service;
|
||||
} catch (e, st) {
|
||||
appLogger.w('BIF thumbnail load failed for part $partId', error: e, stackTrace: st);
|
||||
|
||||
@@ -59,6 +59,7 @@ PlexVideoPlaybackData parsePlexVideoPlaybackDataFromJson(
|
||||
chapters: chapters,
|
||||
partId: part['id'] as int?,
|
||||
displayCriteria: PlexMappers.displayCriteriaFromJson(media as Map<String, dynamic>?, streams.videoStream),
|
||||
videoAspectRatio: ((media as Map?)?['aspectRatio'] as num?)?.toDouble(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ sealed class ScrubFrame {
|
||||
double get aspectRatio;
|
||||
}
|
||||
|
||||
/// Plex BIF: standalone JPEG bytes ready for [Image.memory]. Plex doesn't
|
||||
/// expose per-BIF dimensions out-of-band; servers virtually always use
|
||||
/// 16:9, which matches the default tooltip box.
|
||||
/// Plex BIF: standalone JPEG bytes ready for [Image.memory].
|
||||
class BytesScrubFrame extends ScrubFrame {
|
||||
final Uint8List bytes;
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user