diff --git a/karaoke_downloader/downloader.py b/karaoke_downloader/downloader.py index 1a2745e..d69dbff 100644 --- a/karaoke_downloader/downloader.py +++ b/karaoke_downloader/downloader.py @@ -383,6 +383,67 @@ class KaraokeDownloader: if not videos_to_download: print("šŸŽµ No new videos to download.") return True + + # Create download plan for caching and resuming + download_plan = [] + for video, artist, title, filename in videos_to_download: + download_plan.append({ + "video_id": video["id"], + "artist": artist, + "title": title, + "filename": filename, + "channel_name": channel_name, + "video_title": video.get("title", ""), + "force_download": force_download + }) + + # Cache the download plan for resuming + import hashlib + from karaoke_downloader.cache_manager import get_download_plan_cache_file, save_plan_cache, load_cached_plan + + plan_kwargs = { + "channel": channel_name, + "total_videos": len(available_videos), + "force_download": force_download, + } + if limit: + plan_kwargs["limit"] = limit + + cache_file = get_download_plan_cache_file("all_videos", **plan_kwargs) + + # Check for existing cache + cached_plan, _ = load_cached_plan(cache_file) + if cached_plan and not force_refresh: + print(f"\nšŸ“‹ Found existing download plan cache: {cache_file.name}") + print(f" šŸŽ¬ Cached videos to download: {len(cached_plan)}") + download_plan = cached_plan + else: + # Create new download plan + download_plan = [] + for video, artist, title, filename in videos_to_download: + download_plan.append({ + "video_id": video["id"], + "artist": artist, + "title": title, + "filename": filename, + "channel_name": channel_name, + "video_title": video.get("title", ""), + "force_download": force_download + }) + + # Save the new plan to cache + save_plan_cache(cache_file, download_plan, []) # No unmatched for all-videos mode + + # Show download plan summary + print(f"\nšŸ“‹ Download Plan Summary:") + print(f" šŸ“ŗ Channel: {channel_name}") + print(f" šŸŽ¬ Total videos to download: {len(videos_to_download)}") + print(f" ā­ļø Videos skipped: {skipped_count}") + if limit: + print(f" šŸŽÆ Limit applied: {limit} videos") + print(f" šŸ“ Output directory: downloads/{channel_name}/") + print(f" šŸ’¾ Download plan cached to: {cache_file.name}") + print(f"\nšŸŽ¬ Starting downloads...") # Download videos using the download pipeline pipeline = DownloadPipeline( @@ -394,22 +455,30 @@ class KaraokeDownloader: ) success_count = 0 - for i, (video, artist, title, filename) in enumerate(videos_to_download, 1): - print(f"ā¬‡ļø Downloading {i}/{len(videos_to_download)}: {artist} - {title}") + total_to_download = len(download_plan) + for i, plan_item in enumerate(download_plan[:], 1): # Use slice to create a copy for iteration + print(f"ā¬‡ļø Downloading {i}/{total_to_download}: {plan_item['artist']} - {plan_item['title']}") if pipeline.execute_pipeline( - video_id=video["id"], - artist=artist, - title=title, - channel_name=channel_name, - video_title=video.get("title", ""), + video_id=plan_item["video_id"], + artist=plan_item["artist"], + title=plan_item["title"], + channel_name=plan_item["channel_name"], + video_title=plan_item["video_title"], ): - print(f"āœ… Successfully downloaded: {artist} - {title}") success_count += 1 - else: - print(f"āŒ Failed to download: {artist} - {title}") + # Remove completed item from cache + download_plan.remove(plan_item) # Remove the current item + if download_plan: # If there are still items left + save_plan_cache(cache_file, download_plan, []) + print(f"šŸ—‘ļø Removed completed item from download plan. {len(download_plan)} items remaining.") + else: + # All downloads completed, delete the cache file + from karaoke_downloader.cache_manager import delete_plan_cache + delete_plan_cache(cache_file) + print("šŸ—‘ļø All downloads completed, deleted download plan cache.") - print(f"\nšŸŽ‰ Download complete! {success_count}/{len(videos_to_download)} videos downloaded successfully") + print(f"\nšŸŽ‰ Download complete! {success_count}/{total_to_download} videos downloaded successfully") return success_count > 0 def download_songlist_across_channels(