feat(train): smaller copies of lossless tracks, transcoded by Jellyfin to Opus (ADR 0030, D52)

Smaller copies, on by default on the music screen, has the music job
fetch a file above 256 kbps as Opus at 128 kbps in WebM, but for the
lossy codecs (MP3, AAC, Vorbis, Opus) at any rate. Each track keeps
which copy its file is; switching fetches the other copy without
working out the tempo again, the file kept until the new one is whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-10-29 19:09:06 +01:00
commit 2a7cd927c4
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -36,14 +36,28 @@ class FakeJellyfin({
/// The tracks downloaded, in order.
final downloads = <String>[];
/// A track as Jellyfin lists it.
static Map<String, Object?> track(String id, String name) => {
/// A track as Jellyfin lists it, its file of [codec] at [bitrate] bits a
/// second.
static Map<String, Object?> track(
String id,
String name, {
String codec = 'mp3',
int bitrate = 320000,
}) => {
'Id': id,
'Name': name,
'Type': 'Audio',
'AlbumArtist': 'Band',
'Album': 'Album',
'RunTimeTicks': 1800000000,
'MediaSources': [
{
'Bitrate': bitrate,
'MediaStreams': [
{'Type': 'Audio', 'Codec': codec},
],
},
],
};
void approve() => _approved = true;
@ -117,7 +131,10 @@ class FakeJellyfin({
return http.Response('', 500);
}
downloads.add(id);
return http.Response('audio of $id', 200);
return http.Response(
request.url.path.endsWith('.webm') ? 'opus of $id' : 'audio of $id',
200,
);
case 'POST /Sessions/Logout':
_valid.remove(token);
return http.Response('', 204);
@ -158,10 +175,14 @@ class FakeMusicPlatform([final FakeJellyfin? jellyfin])
final done = {
if (lines.existsSync())
for (final line in lines.readAsLinesSync())
(jsonDecode(line) as Map<String, Object?>)['id'],
if (jsonDecode(line) case {
'id': final String id,
'copy': final String copy,
})
'$id/$copy',
};
for (final track in job.tracks) {
if (done.contains(track.id)) {
if (done.contains('${track.id}/${track.copy.name}')) {
continue;
}
final response = await jellyfin!.client.get(
@ -180,6 +201,7 @@ class FakeMusicPlatform([final FakeJellyfin? jellyfin])
lines.writeAsStringSync(
'${jsonEncode({
'id': track.id,
'copy': track.copy.name,
'bytes': file.lengthSync(),
if (track.analyse) ...{'tempo': tempos[track.id], 'analysed': true},
})}\n',