Music_Splitter / link_processor.py
Omar-youssef's picture
updated
9c75488
raw
history blame
3.07 kB
from pathlib import Path
import yt_dlp
import os
from concurrent.futures import ThreadPoolExecutor
import logging
import shutil
class LinkDownloader:
def __init__(self, output_dir, max_workers=2):
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.executor = ThreadPoolExecutor(max_workers=max_workers)
# Setup logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
self.logger = logging.getLogger(__name__)
def download_from_url(self, url):
"""Downloads a video from the given URL using yt_dlp."""
# Create a unique subdirectory to prevent file conflicts
unique_download_dir = self.output_dir / "download"
unique_download_dir.mkdir(parents=True, exist_ok=True)
temp_filepath = str(unique_download_dir / 'downloaded_video.%(ext)s')
ydl_opts = {
'format': 'best[height<=1080]',
'outtmpl': temp_filepath,
'quiet': False,
'no_warnings': True,
'extract_audio': False,
'concurrent_fragment_downloads': 3,
'file_access_retries': 3,
'retries': 3,
'socket_timeout': 30,
'nocheckcertificate': True,
}
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
# Get video information
info = ydl.extract_info(url, download=False)
ext = info.get('ext', 'mp4')
# Submit download task to executor
future = self.executor.submit(ydl.download, [url])
future.result() # Wait for download to complete
# Find the downloaded file
downloaded_files = list(unique_download_dir.glob(f'downloaded_video.{ext}'))
if not downloaded_files:
self.logger.error("No files found after download.")
return None
# Take the first file (should be the only one)
actual_filepath = str(downloaded_files[0])
if os.path.exists(actual_filepath):
# Copy the file to the main output directory to prevent deletion
final_filepath = str(self.output_dir / f"downloaded_video.{ext}")
shutil.copy2(actual_filepath, final_filepath)
self.logger.info(f"Download completed: {final_filepath}")
return final_filepath
else:
self.logger.error("File not found after download.")
return None
except yt_dlp.DownloadError as e:
self.logger.error(f"yt_dlp error: {e}")
except Exception as e:
self.logger.error(f"Unexpected error: {e}")
return None
def __del__(self):
"""Ensure proper shutdown of the executor."""
self.executor.shutdown(wait=True)
self.logger.info("ThreadPoolExecutor shut down.")