fix(player): update MPVKit and stream buffering

This commit is contained in:
edde746
2026-06-13 20:51:14 +02:00
parent c24a2aade0
commit 9ff3099a9d
11 changed files with 37 additions and 16 deletions
+1 -1
View File
@@ -789,7 +789,7 @@
repositoryURL = "https://github.com/edde746/MPVKit";
requirement = {
kind = revision;
revision = 1fe345d46bac91f4e85239ad268430e037040b2b;
revision = 245b69dce22156e81b79c84cfcb748358b674e47;
};
};
/* End XCRemoteSwiftPackageReference section */
@@ -40,7 +40,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "1fe345d46bac91f4e85239ad268430e037040b2b"
"revision" : "245b69dce22156e81b79c84cfcb748358b674e47"
}
},
{
@@ -40,7 +40,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "1fc33029bc0317583866c62811dc0ab2aa2415b6"
"revision" : "245b69dce22156e81b79c84cfcb748358b674e47"
}
},
{
+1 -1
View File
@@ -763,7 +763,7 @@ class VideoPlayerScreenState extends State<VideoPlayerScreen> with WidgetsBindin
_audioFocusFuture = currentPlayer.requestAudioFocus();
_audioFocusFuture!.ignore();
}
await currentPlayer.setProperty('msg-level', debugLoggingEnabled ? 'all=debug' : 'all=error');
await currentPlayer.setProperty('msg-level', debugLoggingEnabled ? 'all=debug,ffmpeg/video=warn' : 'all=error');
await currentPlayer.setLogLevel(debugLoggingEnabled ? 'v' : 'warn');
await currentPlayer.setProperty('hwdec', _getHwdecValue(enableHardwareDecoding));
+16 -5
View File
@@ -10,9 +10,15 @@ const mpvDefaultStreamBufferBytes = 128 * 1024;
/// in bytes, seconds × video byterate — which makes ffmpeg's DTS-ordered
/// reads ping-pong across the file. Over HTTP every ping-pong that escapes
/// mpv's stream ring buffer is a byte seek, and ffmpeg's http layer drops and
/// redials the connection on every seek, collapsing throughput. MKV is
/// interleaved by spec and excluded.
const poorlyInterleavedContainers = {'mp4', 'mov', 'm4v', '3gp', '3g2'};
/// redials the connection on every seek, collapsing throughput.
const quickTimeFamilyContainers = {'mp4', 'mov', 'm4v', '3gp', '3g2'};
/// Matroska/WebM is normally well-interleaved, but UHD direct-play remuxes can
/// still overrun mpv's tiny 128 KiB default stream ring during normal demuxer
/// read bursts. Only opt in when the server reports a high bitrate so common
/// MKV playback keeps the default memory profile.
const matroskaFamilyContainers = {'mkv', 'matroska', 'webm'};
const _highBitrateMatroskaThresholdKbps = 40 * 1000;
const minStreamRingBytes = 16 * 1024 * 1024;
const maxStreamRingBytes = 128 * 1024 * 1024;
@@ -60,10 +66,15 @@ int? networkStreamRingBytes({
if (container == null) return null;
// Jellyfin may report ffmpeg demuxer alias lists ('mov,mp4,m4a,3gp,3g2,mj2').
final tokens = container.toLowerCase().split(',').map((token) => token.trim());
if (!tokens.any(poorlyInterleavedContainers.contains)) return null;
final isQuickTimeFamily = tokens.any(quickTimeFamilyContainers.contains);
final isMatroskaFamily = tokens.any(matroskaFamilyContainers.contains);
if (!isQuickTimeFamily && !isMatroskaFamily) return null;
final cap = max(minStreamRingBytes, min(maxBytes, maxStreamRingBytes));
if (bitrateKbps == null || bitrateKbps <= 0) return min(unknownBitrateStreamRingBytes, cap);
if (bitrateKbps == null || bitrateKbps <= 0) {
return isQuickTimeFamily ? min(unknownBitrateStreamRingBytes, cap) : null;
}
if (!isQuickTimeFamily && bitrateKbps < _highBitrateMatroskaThresholdKbps) return null;
final bytesPerSecond = bitrateKbps * 1000 ~/ 8;
final ring = nextPowerOfTwo(bytesPerSecond * _streamRingContentSeconds);
+1 -1
View File
@@ -883,7 +883,7 @@
repositoryURL = "https://github.com/edde746/MPVKit";
requirement = {
kind = revision;
revision = 1fe345d46bac91f4e85239ad268430e037040b2b;
revision = 245b69dce22156e81b79c84cfcb748358b674e47;
};
};
/* End XCRemoteSwiftPackageReference section */
@@ -13,7 +13,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "1fc33029bc0317583866c62811dc0ab2aa2415b6"
"revision" : "245b69dce22156e81b79c84cfcb748358b674e47"
}
},
{
@@ -13,7 +13,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "1fc33029bc0317583866c62811dc0ab2aa2415b6"
"revision" : "245b69dce22156e81b79c84cfcb748358b674e47"
}
},
{
+12 -2
View File
@@ -21,12 +21,22 @@ void main() {
});
test('returns null for well-interleaved or unknown containers', () {
expect(networkStreamRingBytes(container: 'mkv', bitrateKbps: 69140), isNull);
expect(networkStreamRingBytes(container: 'avi', bitrateKbps: 69140), isNull);
expect(networkStreamRingBytes(container: null, bitrateKbps: 69140), isNull);
expect(networkStreamRingBytes(container: '', bitrateKbps: 69140), isNull);
});
test('sizes high-bitrate Matroska direct play to 64MiB', () {
expect(networkStreamRingBytes(container: 'mkv', bitrateKbps: 69140), 64 * 1024 * 1024);
expect(networkStreamRingBytes(container: 'matroska', bitrateKbps: 69140), 64 * 1024 * 1024);
});
test('keeps ordinary Matroska direct play on the default stream ring', () {
expect(networkStreamRingBytes(container: 'mkv', bitrateKbps: 39000), isNull);
expect(networkStreamRingBytes(container: 'mkv', bitrateKbps: null), isNull);
expect(networkStreamRingBytes(container: 'mkv', bitrateKbps: 0), isNull);
});
test('matches QuickTime-family containers case-insensitively', () {
expect(networkStreamRingBytes(container: 'MOV', bitrateKbps: 69140), 64 * 1024 * 1024);
expect(networkStreamRingBytes(container: 'mp4', bitrateKbps: 69140), 64 * 1024 * 1024);
@@ -34,7 +44,7 @@ void main() {
test('matches ffmpeg demuxer alias lists from Jellyfin', () {
expect(networkStreamRingBytes(container: 'mov,mp4,m4a,3gp,3g2,mj2', bitrateKbps: 69140), 64 * 1024 * 1024);
expect(networkStreamRingBytes(container: 'matroska,webm', bitrateKbps: 69140), isNull);
expect(networkStreamRingBytes(container: 'matroska,webm', bitrateKbps: 69140), 64 * 1024 * 1024);
});
test('falls back to 64MiB when bitrate is unknown', () {
+1 -1
View File
@@ -933,7 +933,7 @@
repositoryURL = "https://github.com/edde746/MPVKit";
requirement = {
kind = revision;
revision = 1fe345d46bac91f4e85239ad268430e037040b2b;
revision = 245b69dce22156e81b79c84cfcb748358b674e47;
};
};
/* End XCRemoteSwiftPackageReference section */
@@ -6,7 +6,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/edde746/MPVKit",
"state" : {
"revision" : "1fe345d46bac91f4e85239ad268430e037040b2b"
"revision" : "245b69dce22156e81b79c84cfcb748358b674e47"
}
}
],