fix(native-worker): preserve requested output container in finalizer

When the native worker result advertises a requested non-FLAC output extension (for example '.m4a'), skip the m4a-to-flac container conversion in both the Dart and Kotlin finalizers so the native output container is preserved end-to-end.

- ffmpeg_service: propagate the top-level 'output_extension' hint into the download-result descriptor for both the map-backed and legacy paths; expose a normalized getter for consistent comparisons.

- download_queue_provider: short-circuit the native-worker container-conversion step when the descriptor's requested extension is not '.flac', with a debug log describing the skip.

- NativeDownloadFinalizer: mirror the guard on the Kotlin side so the finalizer does not force a container conversion that would clobber the requested native output.
This commit is contained in:
zarzet
2026-05-09 01:23:38 +07:00
parent 904b45e8f6
commit 20ac6b2cd4
3 changed files with 30 additions and 3 deletions
@@ -6049,6 +6049,16 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
if (context.quality == 'HIGH' || context.outputExt != '.flac') {
return filePath;
}
final requestedDecryptionExt =
DownloadDecryptionDescriptor.fromDownloadResult(
result,
)?.normalizedOutputExtension;
if (requestedDecryptionExt != null && requestedDecryptionExt != '.flac') {
_log.d(
'Native-worker decrypted output requested $requestedDecryptionExt; preserving native container.',
);
return filePath;
}
final lowerPath = filePath.toLowerCase();
final resultFileName = (result['file_name'] as String?)?.toLowerCase();
final looksLikeM4a =
+10 -3
View File
@@ -66,9 +66,9 @@ class DownloadDecryptionDescriptor {
) {
final rawDecryption = result['decryption'];
if (rawDecryption is Map) {
final descriptor = DownloadDecryptionDescriptor.fromJson(
Map<String, dynamic>.from(rawDecryption),
);
final descriptorJson = Map<String, dynamic>.from(rawDecryption);
descriptorJson['output_extension'] ??= result['output_extension'];
final descriptor = DownloadDecryptionDescriptor.fromJson(descriptorJson);
if (descriptor.normalizedStrategy == 'ffmpeg.mov_key' &&
descriptor.key.isNotEmpty) {
return descriptor;
@@ -84,6 +84,7 @@ class DownloadDecryptionDescriptor {
strategy: 'ffmpeg.mov_key',
key: legacyKey,
inputFormat: 'mov',
outputExtension: (result['output_extension'] as String?)?.trim(),
);
}
@@ -100,6 +101,12 @@ class DownloadDecryptionDescriptor {
return strategy.trim();
}
}
String? get normalizedOutputExtension {
final trimmed = (outputExtension ?? '').trim().toLowerCase();
if (trimmed.isEmpty) return null;
return trimmed.startsWith('.') ? trimmed : '.$trimmed';
}
}
class FFmpegService {