A multiplatform media downloader
Download songs, albums, playlists, music videos, and more from Apple Music, Spotify, and other services.
- Songs, Albums, Playlists, Artists, Music Videos โ download anything from Apple Music. Non-geographic URLs (without a storefront code) are auto-detected and normalized
- Quality selection with smart fallback chain: ALAC โ Atmos โ AC3 โ AAC Binaural โ AAC โ AAC Legacy
- Companion downloads โ configurable multi-format downloads: automatically download additional codec versions alongside the primary download. Choose from 5 preset modes (Disabled, AtmosโLossless, AtmosโLossless+Lossy, SpecialistโLossy, All Formats) or use Custom mode with multi-select checkboxes to pick exactly which codecs to download as companions. Music video companions โ optionally download the music video for each track alongside audio (requires MusicKit credentials)
- Persistent download queue โ queue survives app close/crash; auto-resumes on restart, failed downloads persist for manual retry. Queue header shows live statistics (active/queued/completed/failed counts) with an aggregate progress bar; album downloads display a "Track N of M" counter
- Queue export/import โ save queue to
.meedyadlfile, transfer to another device - Animated cover art โ automatically download motion artwork (FrontCover.mp4 / FrontCoverPortrait.mp4) via MusicKit API, with optional OS-level file hiding to keep folders clean
- Enhanced LRC with word-by-word sync โ automatically converts Apple Music's TTML lyrics to Enhanced LRC with word-level synchronized timestamps for karaoke-style highlighting in compatible players (foobar2000, Poweramp, AIMP). Falls back to standard line-level LRC for songs without word-level data. Companion lyrics formats (LRC, SRT) remain selectable alongside Enhanced LRC.
- Lyrics format fallback โ if the primary lyrics format isn't available for some tracks, automatically tries alternatives (Audio: TTML โ LRC โ SRT; Video: TTML โ SRT โ LRC)
- Lyrics embed + sidecar โ embed lyrics in file metadata AND save as separate LRC, SRT, or TTML files
- Cover art โ save artwork as JPG, PNG, or raw format at full resolution
- Rich metadata tagging powered by GAMDL
- Comprehensive metadata enrichment โ 30+ freeform atoms per file including: codec/source/channel tags, ISRC, UPC, genre, advisory ratings, artist IDs, record label, copyright, release dates, Apple Digital Master flag, composer, editorial notes, and animated artwork URLs. All sourced from the Apple Music API and written in dual namespaces (
com.apple.iTunesfor player compatibility +MeedyaMetafor MeedyaDL attribution) with industry-standard alternative names (LABEL,COPYRIGHT,COMPILATION,TOTALTRACKS) - Config-driven tag system โ tag definitions live in
tags.toml; adding new metadata tags requires only editing the TOML file โ zero code changes - AcoustID fingerprinting (opt-in) โ Chromaprint audio fingerprints with acoustid.org lookup for MusicBrainz identification. Built-in API key included in release builds; no registration required
- ReplayGain analysis (opt-in) โ non-destructive loudness metadata for volume normalisation in compatible players
- Rich SRT subtitles (opt-in, default: on) โ converts TTML to SRT with styling tags (
<b>,<i>,<u>,<font color>) - ASS subtitles (opt-in) โ converts TTML/WebVTT to Advanced SubStation Alpha with colours, positioning, and background vocal styling
- WebVTT subtitles (opt-in) โ generates
.vttsubtitle files from lyrics sidecars (TTML, SRT, or LRC) - Subtitle embedding (opt-in) โ embeds SRT and WebVTT content directly in MP4 containers as freeform atoms
- MusicBrainz video discovery (opt-in) โ discovers music videos via MusicBrainz database using a 3-tier lookup (Apple Music URL โ ISRC โ AcoustID recording ID). No credentials required. Also discovers cross-platform URLs (YouTube, Spotify, etc.)
- API field audit tool โ developer diagnostic in Settings > Metadata that compares real API responses against known tag definitions, surfacing new fields for review
- Browser cookie auto-import โ detect installed browsers and import Apple Music cookies automatically
- Built-in Apple Music login โ sign in directly within the app to extract cookies (no browser extension needed)
- Cookie file import โ manual Netscape-format cookie import with domain/expiry validation
- Pre-download validation โ multi-provider internet connectivity check (Cloudflare, Google, Apple Music API), output path writability probe (catches disconnected cloud mounts), and cookie validation are checked before every download; offline downloads are queued but deferred until connectivity returns; expired cookies block the download with a link to Settings > Cookies
- Wrapper support โ alternative authentication via a locally-running wrapper service for more reliable Dolby Atmos and DRM-protected format access, with optional auto-retry without wrapper when wrapper downloads fail (see Wrapper Authentication section below)
- Secure credential storage via OS-native keychains (macOS Keychain, Windows Credential Manager, Linux Secret Service)
- macOS โ Liquid Glass-inspired design with native vibrancy
- Windows โ Fluent Design System with Mica/Acrylic effects
- Linux โ Adwaita-inspired styling for GNOME integration
- Auto-update checking โ stay on the latest version with full release notes in the Updates page
- Auto-start queue โ downloads start immediately by default, or toggle off to batch-add URLs and start manually from the Queue page
- Configurable temp directory โ intermediate files stored in
{OS temp}/MeedyaDLby default, customizable in Settings > Paths - First-run setup wizard โ installs Python and GAMDL automatically; detects existing tools from system PATH
- Built-in help documentation โ 12 topics with search, accessible in-app
- System tray support for background operation
- Smart notifications โ toast notifications deduplicate automatically (no more stacking identical messages) and auto-dismiss when their condition resolves (e.g., wrapper warning clears when wrapper becomes reachable)
- Crash reporting โ local crash report logging with optional Sentry telemetry and one-click GitHub Issues reporting (pre-filled issue opened in your browser with privacy preview)
- Graceful shutdown โ background tasks (enrichment, companion downloads, lyrics) stop cleanly on window close or tray quit instead of being abruptly terminated
- Supply chain hardening โ all CI/CD GitHub Actions pinned to immutable commit SHAs, SHA-256 checksum verification for dependency downloads,
cargo-denylicence scanning in CI (org-level source allowlist forMWBMPartnersandMeedyaDLGitHub orgs) - Accessibility โ ARIA labels on interactive elements,
aria-liveregions for dynamic content updates,prefers-reduced-motionsupport, skip navigation, high-contrast mode, colour-blind themes (deuteranopia, protanopia, tritanopia) - i18n groundwork โ translation infrastructure with OS language detection and manual language selection (English, German, French)
- Pre-release version handling โ verbose activity logging persists across restarts during pre-release versions (v0.x.x) for easier debugging; first-load notice modal warns users when a new pre-release version is launched
- Component version info โ Help > About screen displays a Component Library table with installed versions of all tools (Python, GAMDL, FFmpeg, mp4decrypt, N_m3u8DL-RE, MP4Box) via the
get_component_versionsIPC command - Collapsible Help > About sections โ Credits, License, Links, Open Source Acknowledgements, and Component Library are wrapped in
<details>/<summary>elements for clean, scannable layout - CodeQL workflow โ GitHub CodeQL static analysis for Actions YAML and JavaScript/TypeScript. Rust is intentionally excluded (build hangs indefinitely) since Rust code quality is covered by clippy and cargo test in CI
- Brand assets โ vinyl/reel icon design with animated SVG logo and logotype. Brand kit page at
assets/brand/brandkit.html. Colour mode support: light, dark, and 3 colour-blind variants (deuteranopia, protanopia, tritanopia) plus dark variants of each. Sidebar uses animated SVG logo + logotype via<object>tags with static PNG/text fallbacks
| Platform | Architecture | Format | Notes |
|---|---|---|---|
| ๐ macOS | Apple Silicon (ARM64) | .dmg |
Requires macOS 13.3 (Ventura) or later |
| ๐ช Windows | x64 (64-bit) | .exe (NSIS) |
Also works on ARM64 via emulation |
| ๐ช Windows | ARM64 | .exe (NSIS) |
Native ARM64 build |
| ๐ง Linux | x64 | .deb, .AppImage |
Also works on ChromeOS via Crostini |
| ๐ง Linux | ARM64 | .deb |
Raspberry Pi 4/5, ARM servers |
| ๐ง Linux | ARMv7 | .deb |
Raspberry Pi 32-bit (experimental) |
MeedyaDL orchestrates several external components (a portable Python runtime, the GAMDL CLI, and a handful of media tools). Each MeedyaDL release is validated against a specific range of versions for every component. Running outside the validated range may work, but we cannot guarantee functional or security correctness.
| Component | Role | Supported range | Recommended | Source of truth |
|---|---|---|---|---|
| Python | Portable runtime that hosts GAMDL. Bundled with MeedyaDL โ users never install this manually. | 3.10+ | 3.12.x | src-tauri/src/services/python_manager.rs (PYTHON_VERSION) |
| GAMDL | Apple Music download engine. Installed via pip into the bundled Python. |
2.9.1 โ 3.5.1 | 3.5.1 | src-tauri/tool-versions.toml โ [gamdl] |
| FFmpeg | Audio codec conversion and video remuxing. | 5.0+ | 7.x | src-tauri/tool-versions.toml โ [ffmpeg] |
| mp4decrypt (Bento4) | Decrypts Widevine-protected streams. Required by GAMDL v3.0+ for music videos. | 1.6.0+ | 1.6.0+ | src-tauri/tool-versions.toml โ [mp4decrypt] |
| N_m3u8DL-RE | Alternative HLS/DASH downloader used by some codec paths. | 0.4.0+ | 0.5.x | src-tauri/tool-versions.toml โ [nm3u8dlre] |
| MP4Box (GPAC) | Alternative MP4 muxer. | 2.0+ | 2.4+ | src-tauri/tool-versions.toml โ [mp4box] |
| MediaInfo | Audio/video metadata inspection used by the enrichment pipeline. | 22.0+ | 24.x | src-tauri/tool-versions.toml โ [mediainfo] |
- Install flow:
install_gamdl()invokespip install --upgrade 'gamdl>={min},<={max}', so the resolver never pulls a GAMDL release we haven't validated. - Update prompts: the update banner (
services::update_checker) queriesgamdl_capabilities::should_offer_upgrade()โ if PyPI advertises a GAMDL version beyondmaximum_tested_version, no upgrade is suggested. Users who manually upgrade outside the range will still see their installed version, and a startup activity-log entry warns them that downloads may fail on CLI changes until the next MeedyaDL release catches up. - CLI/INI emission:
services::gamdl_capabilitiesis consulted at every subprocess spawn and everyconfig.iniwrite, so MeedyaDL never emits a flag (e.g.--fetch-extra-tags) the installed GAMDL release can't understand.
If you're running MeedyaDL in production and GAMDL ships a new major (e.g. v4.0), please open an issue before upgrading so we can validate and bump the ceiling.
The wrapper is an alternative authentication method for advanced users. Instead of using browser cookies, it connects to a locally-running server that handles Apple ID authentication and DRM key exchange directly.
Most users should stick with cookie-based authentication (the default). The wrapper is useful if you:
- Need more reliable access to Dolby Atmos or other DRM-protected formats
- Experience frequent cookie expiration issues
- Are comfortable running local server software
- Obtain and run the wrapper service โ the wrapper is a separate application (not bundled with MeedyaDL) that listens on
http://127.0.0.1:30020by default - Enable in MeedyaDL โ go to Settings > Advanced and toggle Use Wrapper on
- Configure the URL โ update the Wrapper Account URL if the wrapper runs on a different host or port. If you've moved the wrapper to a different device entirely, see Running the wrapper on a different device below โ there are two more addresses you'll need to update.
When a wrapper download fails (all retries exhausted), MeedyaDL normally shows a "Retry without Wrapper" button on the failed item. If you'd prefer this to happen automatically:
- Go to Settings > Advanced > Wrapper
- Enable Auto-Retry without Wrapper
When enabled, failed wrapper downloads are automatically re-queued with cookie-based authentication โ no manual intervention needed. This is useful if your wrapper is intermittently unavailable and you want downloads to fall back gracefully.
If the wrapper appears connected (the connection test passes, the pre-flight checks all clear) but every track skips with Decryption is not available for media ID: โฆ in the Activity Log, the wrapper's stored Apple Music credentials have most likely gone stale and need re-authenticating.
For Docker installs, stop the container, run the wrapper one-shot in login mode (docker run --privileged --rm -it -v ./rootfs/data:/app/rootfs/data --entrypoint ./wrapper ghcr.io/worldobservationlog/wrapper:local -L "username:password" -H 0.0.0.0), enter your 2FA code if prompted, Ctrl-C once login completes, then start the container again. For native installs, the equivalent is to run the binary once with -L "username:password" to re-sign-in. Full step-by-step + diagnostic guidance lives in the in-app help under Help > Troubleshooting > Wrapper Errors > "Decryption is not available" warnings.
MeedyaDL checks wrapper connectivity in two ways:
- Manual test โ click Test Connection in Settings > Advanced. Shows "Connected (Xms)" on success, or a specific error (timeout, connection refused) on failure.
- Automatic pre-flight check โ every time the download queue starts processing, MeedyaDL pings the wrapper and shows a yellow toast notification if it's unreachable (e.g.,
Wrapper service at http://192.168.3.179:30020 timed out โ check that it is running). The notification auto-dismisses when the wrapper becomes reachable again. Downloads still proceed โ the check is advisory.
You don't have to run the wrapper on the same computer as MeedyaDL. A common setup is to run MeedyaDL on a Mac or Windows PC and the wrapper on a separate Linux box โ for example, a Raspberry Pi sitting on the same home network.
This works, but the wrapper actually uses three connections โ not just one โ and MeedyaDL needs to know about all three. If you only update one or two of them, downloads will appear to start successfully but then fail partway through.
In Settings > Advanced > Wrapper, you'll find three address fields. Update all three to point at the device running the wrapper:
| Setting | What it does | Default |
|---|---|---|
| Wrapper Account URL | The wrapper's account / login service | http://127.0.0.1:30020 |
| Wrapper m3u8 Address | The wrapper's playlist service | 127.0.0.1:20020 |
| Wrapper Decryption Address | The wrapper's decryption service | 127.0.0.1:10020 |
If your wrapper runs on a Raspberry Pi at 192.168.1.50, change them to:
- Wrapper Account URL:
http://192.168.1.50:30020 - Wrapper m3u8 Address:
192.168.1.50:20020 - Wrapper Decryption Address:
192.168.1.50:10020
Note that the host (192.168.1.50) is the same in all three โ only the port number differs.
MeedyaDL will warn you if anything's unreachable. Before each download starts, MeedyaDL quietly checks all three services and shows a yellow warning toast if any of them can't be reached. The warning tells you which service failed and at what address, so you can fix the right setting.
- The wrapper service needs to accept network connections, not just local ones. By default, many wrapper installs only listen on
127.0.0.1(the device itself). If you've installed it via Docker, that usually means the container needs port-forwarding configured (theports:section in yourcompose.yaml); if you've installed it natively, the wrapper's own configuration needs to listen on0.0.0.0instead of127.0.0.1. - A firewall on the wrapper's device may be blocking the ports. On Linux, run something like
sudo ufw allow 30020/tcp(and the same for20020and10020). - Forgetting to update all three settings. If the Account URL points at the Raspberry Pi but the Decryption Address still says
127.0.0.1, MeedyaDL will fetch metadata fine but downloads silently fail at the decryption stage. The pre-download warnings catch this. - You need three free ports on the same device. The wrapper can't share its three ports with anything else on its host, but the host can run other services on different ports.
If you'd rather not change MeedyaDL's settings at all, you can forward all three ports through SSH from your MeedyaDL machine. From a terminal on the Mac/PC running MeedyaDL:
ssh -L 10020:localhost:10020 -L 20020:localhost:20020 -L 30020:localhost:30020 user@your-pi-addressWhile the SSH session stays open, the three ports on the Mac/PC tunnel through to the same ports on the Raspberry Pi. MeedyaDL can keep its default 127.0.0.1 settings and everything just works. Useful for trying it out before committing to the address-change approach.
If MeedyaDL reports the wrapper is unreachable โ especially when the wrapper runs on a separate device (e.g. a Raspberry Pi, VPS, or Docker container) โ you can diagnose the issue from a terminal on the machine running MeedyaDL:
- Test with curl โ
curl -v http://192.168.x.x:30020(use your actual wrapper URL). "Connection refused" means nothing is listening; "timed out" means the host is unreachable. - Check the wrapper is running on the host โ
docker ps | grep wrapper(Docker) orps aux | grep wrapper(native). Check logs withdocker logs <container> --tail 50. - Check the port is accessible โ on the wrapper host, run
ss -tlnp | grep 30020. If it shows127.0.0.1:30020, the wrapper only accepts local connections โ configure it to bind to0.0.0.0. For Docker, verify port mapping withdocker port <container>. - Check firewalls โ
sudo ufw allow 30020/tcp(Linux), or check your OS firewall settings. Devices on the same LAN usually don't need router port forwarding.
For the full step-by-step troubleshooting guide, see the in-app help (Help > Wrapper > Troubleshooting Wrapper Connectivity).
The Wrapper service only provides native binaries for Linux x86_64. On other platforms, you can run the wrapper remotely on a Linux server or in a Docker container and point MeedyaDL to it via a custom URL. See the in-app help (Help > Wrapper) for detailed remote setup instructions.
MeedyaDL is built with a modern, performance-first tech stack:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ React 19 + TypeScript โ โ Frontend UI
โ Tailwind CSS v4 + Zustand โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Tauri 2.0 IPC โ โ Bridge
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Rust Backend (Tokio) โ โ Native Layer
โ Commands ยท Models ยท Services ยท Utils โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Engine Registry (TOML) โ โ Per-platform routing
โ engines.toml ยท codecs.toml ยท tags.toml โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Embedded Python + pip Engines โ โ Download Engines
โ GAMDL ยท votify ยท yt-dlp ยท ... โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | React 19, TypeScript, Tailwind CSS v4, Zustand | Reactive UI with platform-adaptive themes |
| Framework | Tauri 2.0 | Lightweight native shell, IPC, plugins |
| Backend | Rust, Tokio, Reqwest | Async process management, downloads, credential storage |
| Registry | TOML configs (engines, codecs, tags) | Declarative per-platform engine routing and metadata |
| Engines | Python (standalone), GAMDL, votify, yt-dlp | Service-specific download and decryption |
- Apple Music TTML Lyrics Specification โ comprehensive reverse-engineered reference for Apple's syllable/word/line-level lyric TTML format (the format
meedya-lyricsparses and MeedyaDL relies on for Enhanced LRC generation). Covers endpoint contract, namespaces, granularity tiers, full element/attribute schema, background-vocal handling, and cross-format conversion. Lives in MeedyaSuite-core so it can be shared with sister projects (iLyricsDB, MeedyaConverter).
- Download the latest release for your platform from the Releases page. Most users want the latest Stable release; if you want bleeding-edge builds, pick one of the pre-release channels (see Release channels below).
- Install using your platform's standard method:
- macOS: Open the
.dmgand drag MeedyaDL to Applications - Windows: Run the
.exeinstaller - Linux: Install the
.debor run the.AppImage
- macOS: Open the
- Launch the application.
MeedyaDL publishes across seven channels, ordered from least to most stable. You pick one in Settings > General > Updates and the in-app updater stays on that channel โ it will never auto-downgrade you to a less-stable build, even if a more recent one exists. The discovery filter uses >=, so being on (e.g.) Beta will also surface RC and Stable releases โ but never anything below Beta.
| Channel | Cadence | Trigger | Suffix | Audience |
|---|---|---|---|---|
| Nightly | Daily 00:00 UTC | cron | -nightly.YYYYMMDD |
Testing today's in-flight features; expect bugs |
| Weekly | Sunday 00:00 UTC | cron | -weekly.YYYYMMDD |
Week-old integrations |
| Monthly | 1st of month 00:00 UTC | cron | -monthly.YYYYMMDD |
Monthly preview |
| Alpha | Ad-hoc | push to alpha branch |
-alpha.N (monotonic) |
Feature-complete previews |
| Beta | Ad-hoc | push to beta branch |
-beta.N (monotonic) |
Polishing-stage features |
| RC | Ad-hoc | push to release-candidate branch |
-rc.N (monotonic) |
Release candidates |
| Stable | Per-version | release-please-action merge or version-bump.yml |
no suffix | Production (recommended) |
Moving to a less-stable channel is an explicit action (Settings > General > Updates). Moving back up is equally explicit. Within a channel, auto-updates behave exactly as before.
The four most-experimental tiers (Nightly / Weekly / Monthly / Alpha) are hidden from the channel selector by default and only appear when developer access is unlocked. Beta, RC, and Stable are always visible to all users.
On first launch, the setup wizard will guide you through:
- ๐ฆ Dependency installation โ automatically downloads and installs a standalone Python, GAMDL, votify, and external tools (FFmpeg, mp4decrypt, N_m3u8DL-RE, MP4Box, MediaInfo). If compatible versions are already installed on your system, those are used instead of downloading fresh copies.
- ๐ช Cookie configuration โ import your Apple Music cookies for authentication
- ๐ Output directory โ choose where downloaded music will be saved
- ๐๏ธ Quality preferences โ select your preferred audio codec and fallback chain
๐ก The setup takes a few minutes on first run. Dependencies are sandboxed within the app's data directory, or reused from your system PATH if already installed.
| Tool | Version | Notes |
|---|---|---|
| Node.js | LTS (20+) | Frontend build toolchain |
| npm | 10+ | Comes with Node.js |
| Rust | Stable (1.77+) | Backend compilation |
| Tauri CLI | 2.x | npm install handles this |
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libssl-dev \
libgtk-3-dev# Clone the repository
git clone https://github.com/MWBMPartners/MeedyaDL.git
cd MeedyaDL
# Install frontend dependencies
npm install
# Build the application (debug)
npm run tauri build -- --debug
# Build the application (release)
npm run tauri buildThe built application will be in src-tauri/target/release/bundle/.
For the full project structure, see DEV_NOTES.md.
# Start the frontend dev server + Tauri window with hot reload
npm run tauri devThis launches:
- Vite dev server on
http://localhost:1420with HMR - Tauri native window that loads the dev server
- Rust backend with debug logging (set
RUST_LOG=debugfor verbose output)
| Command | Description |
|---|---|
npm run dev |
Start Vite dev server only |
npm run build |
Build frontend (TypeScript + Vite) |
npm run tauri dev |
Full dev mode (frontend + backend) |
npm run tauri build |
Production build |
npm run type-check |
TypeScript type checking |
npm run lint |
ESLint for src/ |
npm run format |
Prettier formatting |
npm run format:check |
Check formatting without changes |
npm run test |
Run frontend tests (Vitest) |
npm run test:watch |
Run tests in watch mode |
# Check compilation
cd src-tauri && cargo check
# Run clippy linter
cargo clippy -- -D warnings
# Run Rust unit tests
cargo testContributions are welcome! Please follow these guidelines:
This project uses Conventional Commits for automated version bumps and changelog generation:
type(scope): description
# Examples:
feat(download): add fallback quality chain support # โ minor bump, in changelog
fix(settings): resolve cookie validation edge case # โ patch bump, in changelog
refactor(backend): simplify dependency management # โ no bump, in changelog as "Improvements"
chore(deps): update dependencies # โ no bump, hidden from changelog
| Type | Version Bump | Changelog |
|---|---|---|
feat |
Minor (0.X.0) | Features |
fix |
Patch (0.0.X) | Bug Fixes |
refactor |
None | Improvements |
perf |
None | Improvements |
test |
None | Improvements |
chore |
None | Hidden |
docs |
None | Hidden |
ci |
None | Hidden |
Important: Use feat: only for user-visible new functionality. Internal infrastructure, tooling, and config changes should use chore: or refactor: to avoid unnecessary version bumps.
- ๐ด Fork the repository
- ๐ฟ Create a feature branch:
git checkout -b feat/my-feature - ๐พ Commit changes using conventional commits
- โ
Ensure all checks pass:
npm run type-check && npm run test - ๐ฌ Open a pull request against
main
- โ Tauri 2.0 + React 19 foundation with platform-adaptive UI
- โ Full Apple Music download workflow with queue, fallback quality, and retry
- โ Automatic dependency management with first-run setup wizard
- โ CI/CD pipeline with release-please, six-tier channel ladder (Nightly โ Weekly โ Monthly โ Alpha โ Beta โ Stable), automated nightly tag-and-release, and bundled dependencies
- โ Settings UI with 10 configuration tabs
- โ Cookie import (browser auto-detect, built-in login, manual import)
- โ Auto-update checker with in-app download, install, and rollback
- โ System tray integration
- โ Animated cover art via MusicKit API with OS-level file hiding
- โ Configurable companion downloads (5 preset modes + Custom multi-select)
- โ Multi-select artist auto-select (download multiple content types from artist URLs)
- โ Metadata enrichment (codec/source/channel tags, Apple Music API, AcoustID, ReplayGain)
- โ Enhanced LRC with word-by-word synchronized lyrics (TTML โ Enhanced LRC conversion)
- โ Lyrics embed + sidecar (LRC, SRT, TTML)
- โ WebVTT subtitle generation from lyrics sidecars (TTML, SRT, LRC)
- โ MusicBrainz video discovery with 3-tier lookup (URL โ ISRC โ AcoustID recording ID)
- โ Queue persistence, crash recovery, and export/import
- โ Updates page with rendered release notes
- โ In-app help viewer with 12 topics and search
- โ i18n infrastructure (i18next, OS language detection, English)
- โ
Smart re-download detection โ checks download history and Apple Music
lastModifiedDateto detect album changes - โ
Library Scan page โ point MeedyaDL at an existing on-disk music library, find every album it has previously downloaded (via
manifest.meedyadlfiles), surface the artist/album/track-count/codec inventory in a sortable table. Foundation for re-download gap-fill (#717 follow-ups for the smart-retry diff + music-video gap-fill prompts) - โ Per-track activity log separators with codec and auth info
- โ MediaInfo CLI integration for accurate Atmos/AC3 codec detection
- โ
Engine registry (
engines.toml) for per-platform tool priority and fallback - โ
Activity log memory optimization โ 10K entry cap, virtualized rendering (
@tanstack/react-virtual), RAF-batched event ingestion, backend\rsegment coalescing (fixes 14+ GB WebView RAM usage) - โ
macOS in-app updater fix โ corrected updater artifact filename in release workflow so
darwin-aarch64platform is included inlatest.json - โ Clipboard detection queues directly โ clicking "Download" on the clipboard toast adds to queue in one click (no more pre-filling the URL input)
- โ Native OS notifications for clipboard detection โ sent when the window is not focused so URLs are never missed
- โ Activity Log auto-scroll checkbox โ replaces Pause/Resume button with a visible checkbox that auto-unchecks when user scrolls up
- โ Album context in progress bar โ shows "DOWNLOADING... Artist โ Album โ Track" with early metadata fetch; activity log track separators include artist/album context
- โ
Notification style control โ 3-way setting (
in_app_only/native_and_in_app/native_only) for fine-grained notification delivery in Settings > General - โ Download history โ persistent history with search, status icons, codec badges (max 1000 entries)
- โ Companion lyrics fix โ all 4 lyrics conversion formats (LRC, SRT, VTT, ASS) now generated for every companion tier, not just the primary download
- โ
Persistent on-disk activity log (#541) โ every Activity Log event is mirrored to a daily-rotating
activity-YYYY-MM-DD.logfile via a buffered background writer (no hot-path disk I/O, no memory leak). Complete forensic record for bug hunting, unaffected by the 10K in-memory cap or the Verbose filter. Export Disk and Reveal buttons in the Activity Log toolbar; optional custom log path in Settings > Advanced > Diagnostics. 7-day retention.
| Milestone | Version | Service | Engine | Issue | Status |
|---|---|---|---|---|---|
| โ | v2.0.0 | Multi-service architecture | โ | #107 | โ Groundwork done |
| โ | v2.0.0 | Engine priority system | โ | #268 | โ Groundwork done |
| M8 | v2.0.0 | BBC iPlayer | get_iplayer / yt-dlp | #102 | ๐ฒ Planned |
| M9 | v2.1.0 | Spotify | votify | #101 | ๐ฒ Planned |
| M10 | v2.2.0 | YouTube | yt-dlp | #104 | ๐ฒ Planned |
Each milestone adds a new media service with its own CLI subprocess engine, URL parser, settings tab, and help documentation. Engine priority per platform is defined in engines.toml. See Project Plan for full milestone details.
- ๐ฎ Smart Download (#110) โ cross-platform quality optimisation (search all services for the same content, download the best quality)
- ๐ฎ YouTube Music (#103) via gytmdl for music-specific features beyond yt-dlp
- ๐ฎ Full i18n (#111) โ complete translations for German, French, and additional languages
- ๐ฎ Enhanced MusicKit Integration (#108) โ server-side token generation to remove Apple Developer credential requirement
- ๐ฎ Stable rollback (#267) โ option to roll back from pre-release to latest stable version
- ๐ฎ Remote Service Status (#106) โ developer-controlled kill switch for individual media services
- ๐ฎ Anonymous Crash Reporting (#44) โ PHP relay for crash submission without GitHub account
- ๐ฎ Native SwiftUI UI for macOS (#109) โ fully native frontend on Apple Silicon
MIT License
Copyright (c) 2026 MeedyaSuite
This project is licensed under the MIT License โ see the LICENSE file for full details.
The verbatim upstream copyright notices and licence text for the third-party engines and tools that MeedyaDL invokes or bundles (GAMDL, FFmpeg, MP4Box, MediaInfo, mp4decrypt, N_m3u8DL-RE, Python, etc.) are reproduced in THIRD_PARTY_LICENSES.md, which also carries MeedyaDL's written offer for the complete corresponding source code of the LGPL/GPL components shipped in the offline-installer build. The ACKNOWLEDGEMENTS.md file lists the full dependency inventory with versions and one-line purposes.
| Project | Role |
|---|---|
| GAMDL | Apple Music download engine |
| votify | Spotify download engine |
| yt-dlp | YouTube / general-purpose download engine |
| get_iplayer | BBC iPlayer specialist engine |
| Tauri | Lightweight, secure framework for building native apps with web tech |
| python-build-standalone | Portable, self-contained Python builds bundled with the app |
| MediaInfo | Accurate codec detection for enrichment pipeline |
| React | Frontend UI library |
| Zustand | Lightweight state management |
| Tailwind CSS | Utility-first CSS framework |
| Lucide | Beautiful, consistent icon set |
For the full implementation plan, project status, architecture decisions, and development phases, see the Project Plan.
Made with โค๏ธ by MeedyaSuite