feat(plex): migrate video transcoding to HLS
This commit is contained in:
@@ -43,9 +43,9 @@ class CodecUtils {
|
||||
};
|
||||
}
|
||||
|
||||
/// Image-based (bitmap) subtitle codecs. These can't be converted to text;
|
||||
/// during an HTTP/MKV transcode Plex copies the stream into the container and
|
||||
/// the player renders it natively.
|
||||
/// Image-based (bitmap) subtitle codecs. Plex burns these into the video
|
||||
/// when the selected output transport cannot carry a bitmap subtitle
|
||||
/// rendition.
|
||||
static bool isImageSubtitleCodec(String? codec) {
|
||||
if (codec == null) return false;
|
||||
return switch (codec.toLowerCase()) {
|
||||
@@ -61,10 +61,9 @@ class CodecUtils {
|
||||
};
|
||||
}
|
||||
|
||||
/// Subtitle codecs that can be carried inside the HTTP/MKV transcode stream
|
||||
/// (`subtitles=embedded`): text codecs plus the image codecs the MKV target
|
||||
/// supports. Keyed sidecars are delivered separately and are not covered here.
|
||||
static bool isEmbeddableSubtitleCodec(String? codec) {
|
||||
/// Subtitle codecs Plex can deliver in a transcode. Text codecs can become
|
||||
/// segmented HLS WebVTT; image codecs can be burned into the video.
|
||||
static bool isTranscodableSubtitleCodec(String? codec) {
|
||||
return isTextSubtitleCodec(codec) || isImageSubtitleCodec(codec);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import '../mpv/mpv.dart';
|
||||
|
||||
const restartBeforePreviousItemThreshold = Duration(seconds: 3);
|
||||
const plexTranscodeSeekRangeStartTolerance = Duration(milliseconds: 500);
|
||||
const plexTranscodeSeekRangeEndGuard = Duration(milliseconds: 500);
|
||||
const plexTranscodeSeekNoopTolerance = Duration(seconds: 1);
|
||||
|
||||
enum PlexTranscodeSeekAction { nativeSeek, restartTranscode }
|
||||
|
||||
bool shouldRestartBeforePreviousItem(Duration position) {
|
||||
return position > restartBeforePreviousItemThreshold;
|
||||
@@ -17,40 +12,3 @@ Duration clampSeekPosition(Player player, Duration position) {
|
||||
if (duration > Duration.zero && position > duration) return duration;
|
||||
return position;
|
||||
}
|
||||
|
||||
/// Plex MKV-over-HTTP transcodes are only native-seeked inside ranges the
|
||||
/// player reports as locally seekable. Anything outside those ranges needs a
|
||||
/// server-offset transcode restart.
|
||||
PlexTranscodeSeekAction resolvePlexTranscodeSeekAction({
|
||||
required Duration currentPosition,
|
||||
required Duration target,
|
||||
required List<BufferRange> bufferRanges,
|
||||
bool allowBufferedNativeSeek = true,
|
||||
Duration rangeStartTolerance = plexTranscodeSeekRangeStartTolerance,
|
||||
Duration rangeEndGuard = plexTranscodeSeekRangeEndGuard,
|
||||
Duration noopTolerance = plexTranscodeSeekNoopTolerance,
|
||||
}) {
|
||||
final validRanges = bufferRanges.where((range) => range.end >= range.start).toList();
|
||||
if (allowBufferedNativeSeek &&
|
||||
_isInAnyBufferedSeekRange(target, validRanges, startTolerance: rangeStartTolerance, endGuard: rangeEndGuard)) {
|
||||
return PlexTranscodeSeekAction.nativeSeek;
|
||||
}
|
||||
|
||||
if ((target - currentPosition).abs() <= noopTolerance) {
|
||||
return PlexTranscodeSeekAction.nativeSeek;
|
||||
}
|
||||
|
||||
return PlexTranscodeSeekAction.restartTranscode;
|
||||
}
|
||||
|
||||
bool _isInAnyBufferedSeekRange(
|
||||
Duration target,
|
||||
List<BufferRange> ranges, {
|
||||
required Duration startTolerance,
|
||||
required Duration endGuard,
|
||||
}) {
|
||||
for (final range in ranges) {
|
||||
if (target >= range.start - startTolerance && target <= range.end - endGuard) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user