Private
Public Access
0
0
Files
manual_slop/scripts/video_analysis/download_video.py
T

76 lines
1.6 KiB
Python

from __future__ import annotations
import subprocess
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from scripts.video_analysis.error_types import ErrorInfo, make_error
@dataclass
class _Ok:
value: Any
def is_ok(self) -> bool:
return True
def is_err(self) -> bool:
return False
@dataclass
class _Err:
err: ErrorInfo
def is_ok(self) -> bool:
return False
def is_err(self) -> bool:
return True
def ok(value: Any) -> _Ok:
return _Ok(value)
def err(error: ErrorInfo) -> _Err:
return _Err(error)
def validate_output_path(path: Path) -> _Ok | _Err:
if path.exists() and path.is_dir():
return err(make_error("OutputIsDirectory", "validate_output_path", str(path)))
path.parent.mkdir(parents=True, exist_ok=True)
return ok(path)
def build_ydl_args(url: str, output: Path) -> list[str]:
return [
"yt-dlp",
"--format", "bestvideo[ext=mp4]/best",
"--output", str(output),
"--no-warnings",
"--quiet",
url,
]
def download_video(url: str, output: Path) -> _Ok | _Err:
validated = validate_output_path(output)
if validated.is_err():
return validated
completed = subprocess.run(
build_ydl_args(url, output),
capture_output=True,
text=True,
)
log_path = output.with_suffix(".log")
log_path.write_text(
f"# yt-dlp log\n# url: {url}\n# output: {output}\n# returncode: {completed.returncode}\n\nstdout:\n{completed.stdout}\n\nstderr:\n{completed.stderr}\n",
encoding="utf-8",
)
if completed.returncode != 0:
return err(make_error("YtdlpError", "download_video", completed.stderr[:500]))
return ok({"output": str(output), "log": str(log_path), "returncode": completed.returncode})