Open
Conversation
- Add apple-music-downloader directory with scripts and documentation - download_apple_music.sh: Download ALAC lossless audio from Apple Music URLs - Supports --auto-wrapper flag for automatic wrapper management - Uses Docker for apple-music-downloader component - Requires wrapper (decryption server) to be running - wrapper.sh: Manage wrapper service (start/stop/restart/status) - setup.sh: Verify dependencies and pull Docker images - README.md: Comprehensive documentation with references to upstream projects - .env.template: Configuration template for credentials and settings - Update main README.md to reference new downloader - Update .gitignore to exclude .env and wrapper runtime files Add ALAC availability check and format documentation improvements - Add check_format.sh script to check available formats before downloading - Update download_apple_music.sh to check for ALAC availability and error if not available - Clarify Dolby Atmos is lossy (EC3 codec) on Apple Music, not lossless TrueHD - Add detailed format explanations (aac-lc, MV, Dolby Atmos) in README - Update .env.template with clearer explanations of optional credentials - Prevent accidental downloads of lossy formats by enforcing ALAC-only downloads Simplify wrapper binary download logic Remove version tracking complexity - always download latest binary and let Docker's build cache handle rebuild detection automatically Switch wrapper to Docker container management - Refactor wrapper.sh to manage Docker container instead of local binary - Update README to document Docker-based wrapper setup - Update .gitignore to ignore wrapper-repo/ instead of wrapper binary - Clarify that .env file is optional with sensible defaults Consolidate configuration variables at top of setup.sh Move all static configuration variables to the top of the script for better organization and consistency
- Update setup.sh to handle zip file downloads and extraction - Add x86_64 fallback for Apple Silicon (arm64) when arm64 binary unavailable - Add --platform linux/amd64 flag to docker run commands for Apple Silicon compatibility - Update README with architecture-specific notes and troubleshooting - Document zip extraction and Rosetta 2 usage Reorganize download output structure and improve format check - Format check is already integrated into download script (no separate docker run for check_format.sh) - Reorganize files after download: ALAC/[Artist]/[Release] -> Apple Music Downloads/[Artist - Release Name] - Flatten directory structure for easier browsing - Update README with new output directory structure Add support for multiple URLs in download script - Accept multiple URLs as arguments (one to many) - Check all URLs in a single docker run (--debug mode) - Download all URLs in a single docker run (more efficient) - Reorganize all downloaded files after completion - Update help text and README with multiple URL examples - Reduces docker runs from 2N (N URLs) to 2 (one check, one download) Add quality controls and output directory flag - Add --output-dir flag to specify download directory (replaces env var) - Add --alac-max flag to override maximum sample rate - Auto-detect bit depth and set sample rate limits: * 16-bit: max 44.1 kHz (CD quality) * 24-bit: max 48 kHz (high-res) - Remove APPLE_MUSIC_OUTPUT_DIR from .env.template - Update README with new flags and quality documentation - Bit depth is determined by Apple Music (not configurable) Refactor format checking logic and remove unnecessary wrapper checks - Move all format checking and validation logic to check_format.sh - Make check_format.sh both a standalone script and a sourceable library - download_apple_music.sh now sources check_format.sh to use shared function - Eliminates code duplication (~155 lines removed from download script) - check_format.sh supports multiple URLs and validates all formats - Remove wrapper checks from check_format.sh standalone execution - Format checking with --debug only queries metadata, doesn't need wrapper - Makes format checks faster by skipping unnecessary checks - Wrapper is only needed for actual downloading/decryption - Fix dependency structure - download_apple_music.sh now sources wrapper_utils.sh directly - check_format.sh no longer sources wrapper_utils.sh (doesn't need it) - Each script now sources only what it needs directly - Clean up check_format.sh - Remove unused WRAPPER_HOST, WRAPPER_PORT variables - Remove unused check_wrapper() function - Add comments explaining why wrapper isn't needed for format checks Add platform compatibility note and fix wrapper startup - Add note about Apple Silicon vs x86_64 compatibility in README - Remove error output suppression in wrapper.sh to see actual errors - Add --platform linux/amd64 flag to wrapper container for Apple Silicon Simplify validation: remove bit depth/sample rate pairing constraint - Remove pairing constraint between bit depth and sample rate - Validation now only checks: minimum 16-bit, minimum 44.1 kHz - Default max sample rates: 44.1 kHz for 16-bit, 48 kHz for 24-bit - --max-sample-rate flag supports 44100, 48000, 96000, 192000 Hz - Update README to reflect simplified validation rules - Fixes issue where 24-bit/44.1 kHz was incorrectly rejected Improve download script resilience for long-running downloads - Move reorganize_files function definition early so cleanup can use it - Reorganize existing ALAC files at script start (handles interrupted downloads) - Add reorganization to cleanup function for error/timeout cases - Improve error messages and handling for interrupted downloads - Add note to README about long downloads and automatic reorganization - Make reorganize_files idempotent and more robust Add named container for downloader to prevent concurrent downloads Extract shared architecture detection and update documentation - Create detect_wrapper_architecture.sh for shared architecture detection - Update setup.sh and wrapper.sh to use shared detection script - Update README to reflect native arm64 wrapper support - Document platform-specific Docker image naming - Clarify wrapper runs natively on Apple Silicon (no emulation) Fix downloader image pull for Apple Silicon - Use --platform linux/amd64 when pulling downloader image on arm64 - Make downloader pull failure non-fatal (download script will pull when needed) - Clarify that downloader uses Rosetta 2 on Apple Silicon
- Remove check_wrapper_restarting() and show_restart_error() functions
- Restart detection was not reliably catching restart loops
- Simplifies codebase by removing complex detection logic
- Simplify wrapper.sh start logic
- Just checks if container is running after brief wait
- No complex restart detection
- Remove restart checks from download_apple_music.sh and check_format.sh
- Wrapper issues will be evident from downloader connection failures
- Connection errors (e.g., 'dial tcp 127.0.0.1:10020: connect: connection refused')
clearly indicate wrapper problems
- Update documentation
- Note that wrapper issues show up as connection failures in downloader logs
- Users can check wrapper logs directly: docker logs apple-music-wrapper
Note: This removes the restart detection that was added in a previous commit,
as it proved unreliable in practice.
Consolidate wrapper utilities and clarify architecture information
- Merge detect_wrapper_architecture.sh into wrapper_utils.sh
- All wrapper-related utilities now in one place
- Architecture detection auto-runs when sourced
- Maintains same functionality with cleaner structure
- Default to x86_64 on Apple Silicon (no flag needed)
- Removed FORCE_WRAPPER_X86_64 flag (now default behavior)
- USE_WRAPPER_ARM64=0 explicitly set in .env.template
- Better user experience - works out of the box
- Show clear architecture information in logs
- Show both system architecture and wrapper/downloader architecture
- Make it clear when using x86_64 as a workaround on Apple Silicon
- Add architecture info to setup.sh, wrapper.sh, and download_apple_music.sh
- Format: 'System: arm64 (Apple Silicon) | Wrapper: x86_64 (Rosetta 2)'
- Format: 'System: arm64 (Apple Silicon) | Downloader: x86_64 (no arm64 build available - using Rosetta 2)'
- Update documentation
- Reflect consolidation of architecture detection
- Update .env.template comments
- Clarify default behavior on Apple Silicon
Remove Dockerfile patching and default to native arm64 on Apple Silicon
The wrapper binary is compiled with Android NDK and links against Android
Apple Music app libraries - this is by design for decryption. Running x86_64
Android NDK binaries on Apple Silicon requires QEMU emulation (not Rosetta 2)
which crashes with segmentation faults. Native arm64 is now the default.
- Remove Dockerfile patching code (tzdata/env vars didn't help)
- Default to arm64 on Apple Silicon (native, no emulation)
- Change env var from USE_WRAPPER_ARM64 to USE_WRAPPER_X86_64
- Update documentation and messaging throughout
Fix docker build to use repo's Dockerfile instead of Dockerfile.simple
Create simple Dockerfile for prebuilt binaries (repo's Dockerfile is incomplete)
Use repo's Dockerfile and clone arm64 branch on Apple Silicon
- Remove all custom Dockerfile code (it doesn't work)
- Clone arm64 branch on Apple Silicon (has complete Dockerfile with entrypoint.sh)
- Clone main branch on x86_64
- Use repo's Dockerfile directly without modifications
Remove explicit --platform from docker commands
The correct branch (arm64 or main) is now cloned based on system architecture,
and the Dockerfile handles platform configuration internally. No need to
override with --platform flag.
- Remove --platform from docker build in setup.sh
- Remove --platform from docker run in wrapper.sh
- Remove unused DOCKER_PLATFORM variable from wrapper_utils.sh
- Update README and comments accordingly
…c use) Fix Apple Silicon support: require credentials and add 2FA workflow The arm64 wrapper binary requires login credentials to stay running. This adds credential validation on Apple Silicon, 2FA support via file input, and removes the broken x86_64 option that crashed with QEMU. Also fixes Dockerfile restoration after extracting release zip to ensure the correct (main branch) Dockerfile is used with arm64 shared libraries. Use cached session instead of forcing re-authentication on every start The wrapper docs show a two-step process: login once with -L flag, then run without -L to use cached session. We were passing -L on every start, causing 2FA prompts on restarts and potential instability during decryption. Now checks for accounts.sqlitedb to determine if session is cached. Added 'login' command to force re-authentication when needed. Add interactive 2FA input when wrapper requests code Fix restart 2FA loop: separate login container from server The server container was started with -L (login) on first run. When it crashed during decryption, Docker restarted it with the same args, so it tried to re-authenticate and asked for 2FA again. Now use a short-lived login container (-L -F) for auth + 2FA only, then stop it. Start the long-lived server with -H only. Restarts use cached session and never re-auth. Troubleshooting: decryption crash (OOM check), device limit - Decryption crash: add docker inspect / ps commands to check exit 137 (OOM) - New section "You've reached your device limit": Apple Music concurrent device limit, how to free devices, use cached session to avoid re-auth
…ion fails - Platform Compatibility + Apple Silicon troubleshooting: local works with single-track, crashes with albums/too many; link to Decryption fails - download_apple_music.sh: warn when arm64 that album/multi-track may crash - wrapper.sh: note on arm64 start about single-track vs album
julientregoat
commented
Jan 25, 2026
apple-music-downloader/README.md
Outdated
|
|
||
| ## Quality | ||
|
|
||
| **ALAC (lossless) is the default and highest quality format.** The downloader automatically selects ALAC if available, falling back to other formats only if ALAC is not available for a specific track. |
Owner
Author
There was a problem hiding this comment.
incorrect, ONLY alac lossless allowed
apple-music-downloader/README.md
Outdated
| ``` | ||
|
|
||
| **Options:** | ||
| - `--auto-wrapper` - Automatically start wrapper if not running, and stop it if this script started it (after download completes) |
Owner
Author
There was a problem hiding this comment.
FIXME remove this functionality, and flag + envvar used to toggle it
julientregoat
commented
Jan 25, 2026
apple-music-downloader/setup.sh
Outdated
| echo "" | ||
|
|
||
| # Note about Apple Silicon requirements | ||
| if [[ "$(uname -m)" == "arm64" ]] || [[ "$(uname -m)" == "aarch64" ]]; then |
Owner
Author
There was a problem hiding this comment.
duplicates wrapper arch detection logic; can this be moved later in the file and use those envvars?
apple-music-downloader/setup.sh
Outdated
| WRAPPER_IMAGE="${WRAPPER_IMAGE_BASE}-${WRAPPER_IMAGE_SUFFIX}" | ||
|
|
||
| # Show clear architecture information | ||
| SYSTEM_ARCH=$(uname -m) |
Owner
Author
There was a problem hiding this comment.
duplicates wrapper utils arch detection logic i think? same as top of file does
…ame -m calls - Moved wrapper_utils.sh sourcing earlier in setup.sh (before first architecture check) - Replaced all uname -m calls with WRAPPER_ARCH variable from wrapper_utils.sh - Simplified architecture checks from checking both arm64/aarch64 to using WRAPPER_ARCH - Centralizes architecture detection logic in wrapper_utils.sh - All files now source wrapper_utils.sh before using WRAPPER_ARCH
- Update README.md to clarify that scripts error out if ALAC is not available - Remove incorrect mentions of fallback behavior to other formats - Update format descriptions (aac-lc, Dolby Atmos, other formats) to state they are not used - Update comment in download_apple_music.sh to clarify no fallback behavior
- Remove --auto-wrapper flag and APPLE_MUSIC_AUTO_WRAPPER env var - Simplify wrapper check to only error if not running (no auto-start) - Remove wrapper shutdown logic at end of script - Update .env.template to remove APPLE_MUSIC_AUTO_WRAPPER - Update README.md to remove all auto-wrapper references - Treat wrapper as long-lived service that should be started manually
- Rename wrapper_utils.sh to utils.sh for generic architecture detection - Simplify to only export SYSTEM_ARCH (remove wrapper-specific variables) - Update all scripts to use SYSTEM_ARCH and compose wrapper values when needed - Make credentials required on all architectures (not just Apple Silicon) - Remove dead fallback logic and unnecessary checks - Simplify release fetching: remove non-zip fallback, inline URLs - Remove redundant logging and architecture-specific branches - Clean up variable naming: prefix wrapper-specific vars with WRAPPER_ - Update documentation to reflect credentials always required
- Add generic container utilities: container_is_running(), container_exists(), cleanup_container() - Add generic network utility: check_port() - Replace duplicated container checks in wrapper.sh and download_apple_music.sh - Remove wrapper-specific is_running() function in favor of generic container_is_running() - Remove wrapper-specific check_wrapper() function in favor of generic check_port() - Reduce code duplication and improve maintainability
- Add DOWNLOADER_IMAGE constant, load_env(), and require_docker() to utils.sh - Remove duplicate .env loading blocks from all scripts (now use load_env) - Remove duplicate DOWNLOADER_IMAGE definitions (now exported from utils.sh) - Remove duplicate Docker checks (now use require_docker) - Consolidate duplicate help text in download_apple_music.sh into show_usage() - Fix bug: remove `local` keyword outside function in check_format.sh
- Reduce README from 479 to 191 lines (60% reduction) - Remove remote wrapper section (unimplemented functionality) - Consolidate redundant mentions of credentials, Apple Silicon warnings, ALAC defaults - Add back useful context: format explanations, related projects usage, media-user-token details - Simplify code comments while preserving important architectural explanations - Restore function usage hints in utils.sh and two-phase login explanation in wrapper.sh
- Extract login logic from wrapper.sh into authenticate_wrapper() function - Simplify reorganize_files() using shorter conditional syntax - Combine regex patterns in check_format.sh format parsing - Simplify output directory assignment using parameter expansion
- Use print0 and explicit loop to process each file exactly once - Add sort to ensure consistent ordering when finding extracted binary - Skip wrapper.zip explicitly to avoid deleting file we're about to download
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
TODO before merge:
Summary
This PR adds Apple Music lossless downloader support to the scripts repo. It uses Docker for both the wrapper (decryption server) and the downloader (zhaarey/apple-music-downloader).
What's included
setup.sh– Installs MP4Box, clones the wrapper repo, downloads the latest prebuilt binary (arm64 or x86_64), builds the wrapper Docker image, and pulls the downloader image.wrapper.sh– Manages the wrapper container (start/stop/restart/status, login). Uses a short-lived login container for 2FA, then a long-lived server container with-Honly so restarts use the cached session.download_apple_music.sh– Downloads ALAC from Apple Music URLs. Checks wrapper reachability, optionally auto-starts wrapper, runs the downloader in Docker.wrapper_utils.sh– Shared architecture detection (arm64 vs x86_64).check_format.sh– Checks ALAC availability for URLs without downloading.Platform notes