101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
import subprocess
|
||
import os
|
||
from datetime import datetime
|
||
import concurrent.futures
|
||
|
||
formats = "18"
|
||
cookies_file = "cookies.txt"
|
||
output_template = "%(id)s/%(id)s.f%(format_id)s.%(ext)s"
|
||
output_infojson = "infojson:%(id)s/%(id)s.t%(duration_string)s.%(ext)s"
|
||
paths = "~/Downloads/staging"
|
||
paths_temp = "temp:~/Downloads/temp"
|
||
cache_dir = "~/Downloads/cache"
|
||
ffmpeg_location = "~/"
|
||
num_threads = 16
|
||
|
||
url_file = "video_urls.txt"
|
||
log_file = "download_log.txt"
|
||
successful_downloads_file = "successful_downloads.txt"
|
||
failed_downloads_file = "failed_downloads.txt"
|
||
|
||
def load_downloaded_urls(file):
|
||
if os.path.exists(file):
|
||
with open(file, "r") as f:
|
||
return set(line.strip() for line in f if line.strip())
|
||
return set()
|
||
|
||
def save_downloaded_url(file, url):
|
||
with open(file, "a") as f:
|
||
f.write(f"{url}\n")
|
||
|
||
def download_video(url):
|
||
if url in successful_downloads:
|
||
print(f"Video {url} already downloaded. Skipping.")
|
||
return
|
||
if url in failed_downloads:
|
||
print(f"Video {url} previously failed. Retrying.")
|
||
|
||
# Проверяем, существует ли актуальный файл cookies
|
||
if not os.path.exists(cookies_file):
|
||
print("ERROR: Cookies file is missing. Stopping execution.")
|
||
exit(1)
|
||
|
||
start_time = datetime.now()
|
||
try:
|
||
command = [
|
||
"yt-dlp",
|
||
"--paths", paths,
|
||
"--paths", paths_temp,
|
||
"--cache-dir", cache_dir,
|
||
"--ffmpeg-location", ffmpeg_location,
|
||
"--format", formats,
|
||
"--cookies", cookies_file, # Используем всегда актуальный файл cookies
|
||
"--output", output_template,
|
||
"--output", output_infojson,
|
||
"--ignore-config",
|
||
"--no-progress",
|
||
"--write-info-json",
|
||
url
|
||
]
|
||
print(f"Start: {' '.join(command)}")
|
||
result = subprocess.run(command, check=True, capture_output=True, text=True)
|
||
end_time = datetime.now()
|
||
log_download(url, start_time, end_time)
|
||
save_downloaded_url(successful_downloads_file, url)
|
||
except subprocess.CalledProcessError as e:
|
||
error_message = e.stderr if e.stderr else str(e)
|
||
print(f"ERROR VIDEO {url}: {error_message}")
|
||
if "This video has been removed" in error_message or "Video unavailable" in error_message:
|
||
save_downloaded_url(failed_downloads_file, url)
|
||
if "Sign in to confirm you’re not a bot" in error_message:
|
||
print("Critical error detected: Sign-in required. Stopping execution.")
|
||
exit(1)
|
||
|
||
def log_download(url, start_time, end_time):
|
||
with open(log_file, "a") as log:
|
||
log.write(f"{url} Download.\nStart: {start_time}\nEnd: {end_time}\n\n")
|
||
|
||
if not os.path.exists(url_file):
|
||
print(f"File {url_file} Empty.")
|
||
exit(1)
|
||
|
||
successful_downloads = load_downloaded_urls(successful_downloads_file)
|
||
failed_downloads = load_downloaded_urls(failed_downloads_file)
|
||
|
||
with open(url_file, "r") as file:
|
||
video_urls = [line.strip() for line in file if line.strip()]
|
||
|
||
video_urls = [url for url in video_urls if url not in successful_downloads]
|
||
|
||
os.makedirs(os.path.expanduser("~/Downloads/staging"), exist_ok=True)
|
||
os.makedirs(os.path.expanduser("~/Downloads/temp"), exist_ok=True)
|
||
os.makedirs(os.path.expanduser("~/Downloads/cache"), exist_ok=True)
|
||
|
||
with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
|
||
futures = [executor.submit(download_video, url) for url in video_urls]
|
||
for future in concurrent.futures.as_completed(futures):
|
||
try:
|
||
future.result()
|
||
except Exception as e:
|
||
print(f"ERROR: {e}")
|