Add download preview flow and search fallback
Some checks failed
build-push / docker (push) Has been cancelled

This commit is contained in:
AI Assistant
2026-03-12 16:01:19 +09:00
parent 5d0ba114ee
commit e136650790
5 changed files with 312 additions and 48 deletions

View File

@@ -5,6 +5,7 @@ import os
import subprocess
import sys
import tempfile
from typing import List
def emit(status, progress, message="", output=""):
@@ -25,14 +26,74 @@ def run(cmd):
return proc
def parse_duration(value):
if value is None:
return "00:00:10"
total = int(float(value))
hours = total // 3600
minutes = (total % 3600) // 60
seconds = total % 60
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
def format_label(height, ext):
if height:
return f"{height}p ({ext})"
return f"Best ({ext})"
def build_quality_options(formats: List[dict]):
heights = []
for item in formats:
height = item.get("height")
if isinstance(height, int) and height > 0:
heights.append(height)
unique_heights = sorted(set(heights))
options = [{"value": "best", "label": "Best available"}]
for height in unique_heights:
options.append(
{
"value": f"bestvideo[height<={height}]+bestaudio/best[height<={height}]",
"label": f"Up to {height}p",
}
)
return options
def probe(url):
cmd = ["yt-dlp", "--dump-single-json", "--no-playlist", url]
proc = run(cmd)
payload = json.loads(proc.stdout)
thumbnail = payload.get("thumbnail") or ""
duration = payload.get("duration")
formats = payload.get("formats") or []
preview = {
"title": payload.get("title") or "Untitled",
"thumbnail": thumbnail,
"durationSeconds": duration or 0,
"duration": parse_duration(duration),
"startDefault": "00:00:00",
"endDefault": parse_duration(duration),
"qualities": build_quality_options(formats),
}
print(json.dumps(preview), flush=True)
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--mode", choices=["probe", "download"], default="download")
parser.add_argument("--url", required=True)
parser.add_argument("--start", default="00:00:00")
parser.add_argument("--end", default="00:00:10")
parser.add_argument("--output", required=True)
parser.add_argument("--quality", default="best")
args = parser.parse_args()
if args.mode == "probe":
probe(args.url)
return
os.makedirs(os.path.dirname(args.output), exist_ok=True)
emit("starting", 5, "Resolving media stream")
@@ -42,7 +103,7 @@ def main():
"yt-dlp",
"--no-playlist",
"-f",
"mp4/bestvideo*+bestaudio/best",
args.quality,
"-o",
source_path,
args.url,