forked from Foxyz/sync_replay_project
Relay picks the most compact video codec (HEVC, AV1, VP9, then h264)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a4be24a2a5
commit
dbfd351ee4
3 files changed
+28
-11
No files matched your search
@@ -512,8 +512,9 @@ all three link modes. Nothing is bundled or installed by hand.
|
||||
- the best single file (`pickSingleFile`: video and audio not `none`, a
|
||||
video container, tallest up to 1080p, else the shortest above), unless
|
||||
- a video-only + audio-only pair is taller (`pickSplit`): video tallest
|
||||
up to 1080p (else the shortest above), avc1 before vp9 before av01
|
||||
(hardware decoding), then bitrate; audio the original language, not a
|
||||
up to 1080p (else the shortest above), HEVC before AV1 before VP9
|
||||
before h264 (the most compact first: relayed bytes cost every viewer
|
||||
and the server buffer, and mpv decodes them all), then bitrate; audio the original language, not a
|
||||
`-drc` variant unless alone, m4a/aac before opus, then bitrate.
|
||||
YouTube has only these (299 + 140 for a 1080p60 video).
|
||||
- Neither (only HLS/DASH playlists) or a live stream: nothing to relay.
|
||||
|
||||
@@ -161,18 +161,23 @@ YtDlpFormat? pickSingleFile(List<Object?> formats, {int maxHeight = 1080}) {
|
||||
return YtDlpFormat._of(ok.first);
|
||||
}
|
||||
|
||||
// Relayed bytes cost every viewer bandwidth and the server buffer, and mpv
|
||||
// decodes all of these: the most compact codec first. HEVC (hardware
|
||||
// decoding nearly everywhere), then AV1 (smallest; software is fine to
|
||||
// 1080p), then VP9, then h264.
|
||||
int _videoCodecRank(Map f) {
|
||||
final c = '${f['vcodec']}'.toLowerCase();
|
||||
if (c.startsWith('avc') || c.startsWith('h264')) return 0;
|
||||
if (c.startsWith('vp9') || c.startsWith('vp09')) return 1;
|
||||
if (c.startsWith('av01')) return 2;
|
||||
return 3;
|
||||
if (c.startsWith('hvc') || c.startsWith('hev') || c.startsWith('h265')) return 0;
|
||||
if (c.startsWith('av01')) return 1;
|
||||
if (c.startsWith('vp9') || c.startsWith('vp09')) return 2;
|
||||
if (c.startsWith('avc') || c.startsWith('h264')) return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
/// The best video-only + audio-only pair of plain http(s) files (YouTube's
|
||||
/// DASH formats), or null. Video: the tallest up to [maxHeight] (else the
|
||||
/// shortest above), avc1 before vp9 before av01 (hardware decoding), then
|
||||
/// bitrate. Audio: the original language, not a `-drc` variant, m4a/aac
|
||||
/// shortest above), HEVC before AV1 before VP9 before h264 (smallest
|
||||
/// first, see [_videoCodecRank]), then bitrate. Audio: the original language, not a `-drc` variant, m4a/aac
|
||||
/// before others (opus), then bitrate.
|
||||
(YtDlpFormat, YtDlpFormat)? pickSplit(List<Object?> formats, {int maxHeight = 1080}) {
|
||||
final video = [
|
||||
|
||||
@@ -90,10 +90,10 @@ void main() {
|
||||
_f('96', 'm3u8_native', 'avc1', 'mp4a', 1080),
|
||||
];
|
||||
|
||||
test('YouTube: avc1 video up to 1080p (highest bitrate) + m4a audio, with the chunk size', () {
|
||||
test('YouTube: the most compact codec up to 1080p (VP9 over h264 here) + m4a audio, with the chunk size', () {
|
||||
final t = pickTracks(youtube);
|
||||
expect([for (final x in t) (x.kind, x.format.id)], [('video', '299'), ('audio', '140')]);
|
||||
expect(t.first.format.chunkSize, 10485760);
|
||||
expect([for (final x in t) (x.kind, x.format.id)], [('video', '248'), ('audio', '140')]);
|
||||
expect(YtDlpInfo.parse({'title': 'x', 'formats': youtube}).formats['299']?.chunkSize, 10485760);
|
||||
expect(YtDlpInfo.parse({'title': 'x', 'formats': youtube}).formats['137']?.height, 1080);
|
||||
});
|
||||
|
||||
@@ -200,4 +200,15 @@ void main() {
|
||||
await media.close();
|
||||
expect(n, size);
|
||||
}, timeout: const Timeout(Duration(minutes: 3)), skip: Platform.environment['YTDLP_LIVE'] == '1' ? false : 'YTDLP_LIVE not set');
|
||||
|
||||
test('codec order: HEVC, then AV1, then VP9, then h264 at the same height', () {
|
||||
final audio = _f('140', 'https', 'none', 'mp4a.40.2', null);
|
||||
String pick(List<String> codecs) => pickSplit([
|
||||
for (final (i, c) in codecs.indexed) _f('v$i', 'https', c, 'none', 1080),
|
||||
audio,
|
||||
])!.$1.id;
|
||||
expect(pick(['avc1.640033', 'vp09.00.40.08', 'av01.0.08M.08', 'hvc1.1.6.L12']), 'v3');
|
||||
expect(pick(['avc1.640033', 'vp09.00.40.08', 'av01.0.08M.08']), 'v2');
|
||||
expect(pick(['avc1.640033', 'vp09.00.40.08']), 'v1');
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user