From 340b0dea9ed61ee2dc3bccb9ec4b535fc12f0c6e Mon Sep 17 00:00:00 2001 From: Maksim Totmin Date: Sun, 31 May 2026 22:44:02 +0700 Subject: [PATCH] Switch default output to MP3, fix AAC for iPod Nano 7G, auto-remove gray source rows after convert - Separate AAC and MP3 ffmpeg paths: remove +global_header and +genpts from MP3 - Clamp AAC bitrate to 160 kbps (iPod Nano 7G max); warn on override - Make mp3 the default format in UI, converter, and CLI - Auto-remove converted source tracks from library UI (keep files on disk) - Bulk delete_tracks with single scan+sync (progress support) - Async duplicate removal with progress via WorkerThread --- src/audio_converter.py | 50 +++++++++++++++++++++++++----------------- src/cli.py | 2 +- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/audio_converter.py b/src/audio_converter.py index 8ff6cf9..3625c1f 100644 --- a/src/audio_converter.py +++ b/src/audio_converter.py @@ -42,7 +42,7 @@ class AudioConverter: def convert_to_ipod_format(self, track_info: TrackInfo, input_file: str, - format: str = "m4a", + format: str = "mp3", audio_bitrate: int = 256, overwrite: bool = False) -> str: """ @@ -90,24 +90,27 @@ class AudioConverter: logger.warning(f"Existing file is too small ({file_size} bytes), re-converting") os.remove(output_file) - # iPod Nano 7 is strict about AAC parameters: - # - AAC-LC profile only (HE-AAC causes playback issues/crashes) - # - 44100 Hz sample rate (firmware expects this exactly) - # - +global_header: required for iPod AAC decoder init - # - +genpts: fix timestamp gaps from web sources - codec = "aac" if format == "m4a" else "libmp3lame" - cmd = [ - "ffmpeg", "-y", "-fflags", "+genpts", "-i", input_file, - "-c:a", codec, - "-b:a", f"{audio_bitrate}k", - "-ar", "44100", - "-ac", "2", - "-flags", "+global_header", - ] - - # For M4A/AAC: force LC profile and use libfdk_aac if available (best quality), - # otherwise fall back to built-in aac with profile flag if format == "m4a": + # iPod Nano 7 AAC requirements: + # - AAC-LC profile only (HE-AAC causes playback issues/crashes) + # - 44100 Hz sample rate (firmware expects this exactly) + # - Max 160 kbps for stereo (higher may cause truncation/crackle) + # - +global_header: required for iPod AAC decoder init + # - +genpts: fix timestamp gaps from web sources + m4a_bitrate = min(audio_bitrate, 160) + if audio_bitrate > 160: + logger.warning( + "Bitrate %d kbps exceeds iPod Nano 7 max (160 kbps), clamping to 160", + audio_bitrate, + ) + cmd = [ + "ffmpeg", "-y", "-fflags", "+genpts", "-i", input_file, + "-c:a", "aac", + "-b:a", f"{m4a_bitrate}k", + "-ar", "44100", + "-ac", "2", + "-flags", "+global_header", + ] # Try libfdk_aac first (best compatibility) fdkaac_cmd = cmd + [ "-map", "0:a", @@ -129,7 +132,6 @@ class AudioConverter: if "libfdk_aac" in test.stdout: cmd = fdkaac_cmd else: - # Fallback: built-in aac with LC profile cmd += [ "-map", "0:a", "-map", "0:v?", @@ -154,7 +156,15 @@ class AudioConverter: output_file, ] else: - cmd += [ + # MP3 for iPod Nano 7G: reliable, no special decoder flags needed. + # libmp3lame is mature and produces streams safe for hardware decoders. + # No +global_header — that flag is AAC-only and confuses MP3 playback. + cmd = [ + "ffmpeg", "-y", "-i", input_file, + "-c:a", "libmp3lame", + "-b:a", f"{audio_bitrate}k", + "-ar", "44100", + "-ac", "2", "-map", "0:a", "-map", "0:t?", "-id3v2_version", "3", diff --git a/src/cli.py b/src/cli.py index dfe9b8d..71b5905 100644 --- a/src/cli.py +++ b/src/cli.py @@ -155,7 +155,7 @@ class YouTubeToIPodCLI: def convert(self, tracks: List[TrackInfo], output_dir: str, - format: str = "m4a", + format: str = "mp3", quality: int = 256, video: bool = False, resolution: str = "640x480") -> List[Tuple[TrackInfo, str]]: