feat: 新增代码

This commit is contained in:
Daniel
2026-04-07 00:37:39 +08:00
commit 8d0b729f2f
29 changed files with 1768 additions and 0 deletions

View File

View File

@@ -0,0 +1,40 @@
import subprocess
from pathlib import Path
def run_cmd(cmd: list[str]) -> None:
proc = subprocess.run(cmd, capture_output=True, text=True)
if proc.returncode != 0:
raise RuntimeError(f"Command failed: {' '.join(cmd)}\nSTDOUT: {proc.stdout}\nSTDERR: {proc.stderr}")
def frames_to_video(frames_pattern: str, fps: int, output_video_path: Path) -> None:
output_video_path.parent.mkdir(parents=True, exist_ok=True)
cmd = [
"ffmpeg",
"-y",
"-framerate",
str(fps),
"-i",
frames_pattern,
"-pix_fmt",
"yuv420p",
str(output_video_path),
]
run_cmd(cmd)
def extract_first_frame(video_path: Path, first_frame_path: Path) -> None:
first_frame_path.parent.mkdir(parents=True, exist_ok=True)
cmd = [
"ffmpeg",
"-y",
"-i",
str(video_path),
"-vf",
"select=eq(n\\,0)",
"-vframes",
"1",
str(first_frame_path),
]
run_cmd(cmd)

View File

@@ -0,0 +1,24 @@
import json
from pathlib import Path
from typing import Any, Dict
TASK_VIDEO_NAME = "video.mp4"
TASK_FIRST_FRAME_NAME = "first_frame.jpg"
TASK_METADATA_NAME = "metadata.json"
TASK_LOG_NAME = "run.log"
def ensure_dir(path: Path) -> Path:
path.mkdir(parents=True, exist_ok=True)
return path
def task_output_dir(base_output_dir: Path, task_id: str) -> Path:
return ensure_dir(base_output_dir / task_id)
def write_json(path: Path, data: Dict[str, Any]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)

View File

@@ -0,0 +1,12 @@
from pathlib import Path
from PIL import Image, ImageDraw, ImageFont
def make_dummy_frame(path: Path, width: int, height: int, text: str, step: int) -> None:
image = Image.new("RGB", (width, height), color=(25 + step * 5 % 200, 40, 60))
draw = ImageDraw.Draw(image)
font = ImageFont.load_default()
draw.text((16, 16), text, fill=(240, 240, 240), font=font)
draw.text((16, 38), f"frame={step}", fill=(220, 220, 220), font=font)
image.save(path, format="JPEG", quality=90)

View File

@@ -0,0 +1,24 @@
import logging
from pathlib import Path
def build_logger(name: str, log_level: str = "INFO", log_file: Path | None = None) -> logging.Logger:
logger = logging.getLogger(name)
logger.setLevel(getattr(logging, log_level.upper(), logging.INFO))
if logger.handlers:
return logger
formatter = logging.Formatter("%(asctime)s | %(levelname)s | %(name)s | %(message)s")
stream_handler = logging.StreamHandler()
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
if log_file is not None:
log_file.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(log_file, encoding="utf-8")
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
return logger