Feat: Implement yt-dlp integration; Fix: Resolve PyInstaller bundling issues for downloader and ffmpeg-python; Docs: Add command-outputs.md

This commit is contained in:
Ramforth
2025-11-01 15:49:35 +01:00
parent 89c6a25891
commit be101e0869
4 changed files with 812 additions and 1 deletions

71
downloader.py Normal file
View File

@@ -0,0 +1,71 @@
import yt_dlp
import os
import sys
import tempfile
def download_video(url, output_dir=None):
"""Downloads a video from the given URL to a temporary location or specified output directory.
Args:
url (str): The URL of the video to download.
output_dir (str, optional): Directory to save the downloaded file. If None, uses a temporary directory.
Returns:
str: The absolute path to the downloaded video file, or None if download fails.
"""
if output_dir and not os.path.isdir(output_dir):
print(f"Error: Output directory '{output_dir}' for download does not exist or is not a directory.", file=sys.stderr)
return None
temp_dir = None
if not output_dir:
temp_dir = tempfile.TemporaryDirectory() # Create a temporary directory
output_dir = temp_dir.name
ydl_opts = {
'format': 'bestvideo[ext!=webm]+bestaudio[ext!=webm]/best[ext!=webm]', # Prioritize non-webm formats
'outtmpl': os.path.join(output_dir, '%(title)s.%(ext)s'),
'noplaylist': True, # Only download single video, not entire playlist
'progress_hooks': [lambda d: sys.stdout.write(f"Downloading: {d['filename']} - {d['status']}" + '\r') if d['status'] == 'downloading' else None],
'postprocessors': [{
'key': 'FFmpegVideoConvertor',
'preferedformat': 'mp4',
}],
'quiet': True, # Suppress yt-dlp output unless error
'no_warnings': True,
}
downloaded_file_path = None
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info_dict = ydl.extract_info(url, download=True)
downloaded_file_path = ydl.prepare_filename(info_dict)
# yt-dlp might return a path with a different extension if format conversion happened
# We need to find the actual downloaded file
base, ext = os.path.splitext(downloaded_file_path)
if not os.path.exists(downloaded_file_path):
# Try common extensions if the exact path isn't found
for common_ext in ['.mp4', '.mkv', '.webm', '.flv']:
if os.path.exists(base + common_ext):
downloaded_file_path = base + common_ext
break
if not os.path.exists(downloaded_file_path):
print(f"Error: Downloaded file not found at expected path: {downloaded_file_path}", file=sys.stderr)
return None
except yt_dlp.utils.DownloadError as e:
print(f"Error downloading video: {e}", file=sys.stderr)
return None
except Exception as e:
print(f"An unexpected error occurred during download: {e}", file=sys.stderr)
return None
finally:
if temp_dir: # Clean up temporary directory if it was created
# The file might have been moved by yt-dlp, so we only clean up if it's empty
if not os.listdir(temp_dir.name):
temp_dir.cleanup()
else:
print(f"Warning: Temporary directory {temp_dir.name} not empty, not cleaning up automatically.", file=sys.stderr)
return downloaded_file_path