Commit 973df1ca4c51
Changed files (3)
modules
music-playlist-dl
tools
music-playlist-dl
modules/music-playlist-dl/default.nix
@@ -49,7 +49,7 @@ in
baseDir = mkOption {
type = types.str;
default = "/neo/music";
- description = "Base directory for downloads (library and playlists subdirectories)";
+ description = "Base directory for downloads (shows and playlists subdirectories)";
};
schedule = mkOption {
@@ -120,10 +120,9 @@ in
''
);
- # Ensure directories exist
+ # Ensure base directory exists (playlists dir created by script)
ExecStartPre = pkgs.writeShellScript "music-playlist-dl-prepare" ''
- mkdir -p "${cfg.baseDir}/library"
- mkdir -p "${cfg.baseDir}/playlist"
+ mkdir -p "${cfg.baseDir}"
'';
# Resource limits
tools/music-playlist-dl/config.yaml.example
@@ -2,9 +2,11 @@
# Copy this file to /neo/music/music-playlist-dl.yaml and customize
# Base directory for downloads
-# - Downloads go to: {base_dir}/library/{artist}/{show}/
-# - Playlists go to: {base_dir}/playlist/{artist} - {show}.m3u
-base_dir: /neo/music
+# - Downloads go to: {base_dir}/{show}/
+# - Playlists go to: {base_dir}/../playlists/{artist} - {show}.m3u
+# Example base_dir: /neo/music/mixes or /neo/music/podcasts
+# Playlists will be in: /neo/music/playlists/
+base_dir: /neo/music/mixes
# Beets integration (optional, disabled by default)
# Enable this to automatically import podcasts to beets music library manager
@@ -86,21 +88,18 @@ yt_dlp_options:
# After running, your directory structure will look like:
#
# /neo/music/
-# ├── library/
-# │ ├── Above & Beyond/
-# │ │ └── Group Therapy/
-# │ │ ├── .downloaded.txt # Archive file (tracks downloaded IDs)
-# │ │ ├── Group Therapy 657-abc123.m4a
-# │ │ └── Group Therapy 658-def456.m4a
-# │ ├── Armin van Buuren/
-# │ │ └── A State of Trance/
-# │ │ ├── .downloaded.txt
-# │ │ └── ASOT Episode 1255-xyz789.m4a
-# │ └── Tiësto/
-# │ └── CLUBLIFE/
-# │ ├── .downloaded.txt
-# │ └── CLUBLIFE Podcast 908-ghi012.m4a
-# └── playlist/
+# ├── mixes/ # base_dir (or podcasts/)
+# │ ├── Group Therapy/
+# │ │ ├── .downloaded.txt # Archive file (tracks downloaded IDs)
+# │ │ ├── Group Therapy 657-abc123.m4a
+# │ │ └── Group Therapy 658-def456.m4a
+# │ ├── A State of Trance/
+# │ │ ├── .downloaded.txt
+# │ │ └── ASOT Episode 1255-xyz789.m4a
+# │ └── CLUBLIFE/
+# │ ├── .downloaded.txt
+# │ └── CLUBLIFE Podcast 908-ghi012.m4a
+# └── playlists/ # Shared playlists directory
# ├── Above & Beyond - Group Therapy.m3u
# ├── Armin van Buuren - A State of Trance.m3u
# └── Tiësto - CLUBLIFE.m3u
@@ -114,8 +113,8 @@ yt_dlp_options:
# Playlists are standard M3U format with relative paths:
#
# #EXTM3U
-# ../library/Above & Beyond/Group Therapy/Group Therapy 657-abc123.m4a
-# ../library/Above & Beyond/Group Therapy/Group Therapy 658-def456.m4a
+# ../Group Therapy/Group Therapy 657-abc123.m4a
+# ../Group Therapy/Group Therapy 658-def456.m4a
# Podcast Information & Sources
#
@@ -160,7 +159,7 @@ yt_dlp_options:
# 2. Run music-playlist-dl --import-existing to import all existing files once
# 3. Future runs will automatically import new downloads
#
-# Files stay in library/{artist}/{show}/ - beets imports in-place (doesn't move)
+# Files stay in {base_dir}/{show}/ - beets imports in-place (doesn't move)
# This preserves yt-dlp's download archive (.downloaded.txt) for deduplication
#
# Tag Hierarchy:
tools/music-playlist-dl/music-playlist-dl.py
@@ -144,11 +144,11 @@ def build_yt_dlp_command(
def download_mixcloud_show(
- show: MixcloudShow, library_dir: Path, yt_dlp_options: dict
+ show: MixcloudShow, base_dir: Path, yt_dlp_options: dict
) -> bool:
"""Download a Mixcloud show."""
url = f"https://www.mixcloud.com/{show.handle}/"
- output_dir = library_dir / show.artist / show.show
+ output_dir = base_dir / show.show
output_dir.mkdir(parents=True, exist_ok=True)
output_template = str(output_dir / "%(title)s-%(id)s.%(ext)s")
@@ -168,10 +168,10 @@ def download_mixcloud_show(
def download_soundcloud_show(
- show: SoundcloudShow, library_dir: Path, yt_dlp_options: dict
+ show: SoundcloudShow, base_dir: Path, yt_dlp_options: dict
) -> bool:
"""Download a SoundCloud show."""
- output_dir = library_dir / show.artist / show.show
+ output_dir = base_dir / show.show
output_dir.mkdir(parents=True, exist_ok=True)
output_template = str(output_dir / "%(title)s-%(id)s.%(ext)s")
@@ -191,10 +191,10 @@ def download_soundcloud_show(
def generate_playlist(
- artist: str, show: str, library_dir: Path, playlist_dir: Path
+ artist: str, show: str, base_dir: Path, playlist_dir: Path
):
"""Generate M3U playlist for a show."""
- show_dir = library_dir / artist / show
+ show_dir = base_dir / show
if not show_dir.exists():
logging.warning(f"Show directory does not exist: {show_dir}")
return
@@ -233,7 +233,7 @@ def generate_playlist(
def import_to_beets(
- library_dir: Path,
+ base_dir: Path,
artist: str,
show: str,
show_beets_tags: dict,
@@ -243,7 +243,7 @@ def import_to_beets(
if not beets_config.enable:
return True # Skip if disabled
- show_dir = library_dir / artist / show
+ show_dir = base_dir / show
if not show_dir.exists():
logging.warning(f"Show directory does not exist: {show_dir}")
return False
@@ -323,33 +323,33 @@ def main():
sys.exit(1)
# Setup directories
- library_dir = config.base_dir / "library"
- playlist_dir = config.base_dir / "playlist"
- library_dir.mkdir(parents=True, exist_ok=True)
+ base_dir = config.base_dir
+ playlist_dir = base_dir.parent / "playlists"
+ base_dir.mkdir(parents=True, exist_ok=True)
playlist_dir.mkdir(parents=True, exist_ok=True)
logging.info(
- f"Starting music podcast downloads to: {library_dir}"
+ f"Starting music podcast downloads to: {base_dir}"
)
logging.info("=" * 60)
# Download Mixcloud shows
for show in config.mixcloud_shows:
- download_mixcloud_show(show, library_dir, config.yt_dlp_options)
+ download_mixcloud_show(show, base_dir, config.yt_dlp_options)
# Download SoundCloud shows
for show in config.soundcloud_shows:
- download_soundcloud_show(show, library_dir, config.yt_dlp_options)
+ download_soundcloud_show(show, base_dir, config.yt_dlp_options)
logging.info("=" * 60)
logging.info("Generating playlists...")
# Generate playlists for all shows
for show in config.mixcloud_shows:
- generate_playlist(show.artist, show.show, library_dir, playlist_dir)
+ generate_playlist(show.artist, show.show, base_dir, playlist_dir)
for show in config.soundcloud_shows:
- generate_playlist(show.artist, show.show, library_dir, playlist_dir)
+ generate_playlist(show.artist, show.show, base_dir, playlist_dir)
# Import to beets if enabled
if config.beets.enable:
@@ -358,7 +358,7 @@ def main():
logging.info("Importing all existing files to beets...")
for show in config.mixcloud_shows:
import_to_beets(
- library_dir,
+ base_dir,
show.artist,
show.show,
show.beets_tags,
@@ -366,7 +366,7 @@ def main():
)
for show in config.soundcloud_shows:
import_to_beets(
- library_dir,
+ base_dir,
show.artist,
show.show,
show.beets_tags,
@@ -380,7 +380,7 @@ def main():
logging.info("Importing new downloads to beets...")
for show in config.mixcloud_shows:
import_to_beets(
- library_dir,
+ base_dir,
show.artist,
show.show,
show.beets_tags,
@@ -388,7 +388,7 @@ def main():
)
for show in config.soundcloud_shows:
import_to_beets(
- library_dir,
+ base_dir,
show.artist,
show.show,
show.beets_tags,