# -*- coding: utf-8 -*- """ 扫描本地 ./composite/ 下的视频目录,逐个上传到其在 COS 上对应视频目录的 composite/ 子目录, 上传成功后删除本地。视频的 COS 路径从 数据.jsonl 的 video_cos_path 反查。 用法: python upload_composites.py [composite根目录] [数据.jsonl路径] 默认: python upload_composites.py ./composite 数据.jsonl """ import json import os import shutil import subprocess import sys from config.config_utils import config COMPOSITE_ROOT = sys.argv[1] if len(sys.argv) > 1 else "./composite" JSONL_PATH = sys.argv[2] if len(sys.argv) > 2 else "数据.jsonl" def build_cosdir_map(jsonl_path): """从 数据.jsonl 建立 video_name -> cos_dir 映射。""" mapping = {} if not os.path.exists(jsonl_path): print(f"警告: 找不到 {jsonl_path},无法反查 COS 路径") return mapping with open(jsonl_path, encoding="utf-8") as f: for line in f: line = line.strip() if not line: continue try: rec = json.loads(line) except json.JSONDecodeError: continue vid = rec.get("video_cos_path") if not vid: continue cos_dir = vid[:vid.rfind("/") + 1] # 含末尾 / name = os.path.splitext(os.path.basename(vid))[0] mapping[name] = cos_dir return mapping def upload_dir(local_dir, cos_dest_dir, coscli_path, cos_config_path): if not cos_dest_dir.endswith("/"): cos_dest_dir += "/" src = local_dir if local_dir.endswith(os.sep) else local_dir + os.sep cmd = [coscli_path, "-c", cos_config_path, "cp", "-r", src, cos_dest_dir] result = subprocess.run(cmd, capture_output=True, text=True, check=False) return (cos_dest_dir if result.returncode == 0 else None), result.stderr def main(): if not os.path.isdir(COMPOSITE_ROOT): print(f"目录不存在: {COMPOSITE_ROOT}") return cfg = config.get_splitframe_config() coscli_path = cfg.get("coscli_path", "./coscli-linux-amd64") cos_config_path = cfg.get("cosconfig_path", ".cos.yaml") cosdir_map = build_cosdir_map(JSONL_PATH) dirs = [d for d in os.listdir(COMPOSITE_ROOT) if os.path.isdir(os.path.join(COMPOSITE_ROOT, d))] print(f"发现 {len(dirs)} 个本地 composite 目录,开始上传...") ok = fail = skip = 0 for i, name in enumerate(dirs, 1): local_dir = os.path.join(COMPOSITE_ROOT, name) cos_dir = cosdir_map.get(name) if not cos_dir: skip += 1 print(f"[{i}/{len(dirs)}] {name} ✗ 在 数据.jsonl 中找不到 COS 路径,跳过") continue cos_dest = cos_dir + "composite/" uploaded, err = upload_dir(local_dir, cos_dest, coscli_path, cos_config_path) if uploaded: shutil.rmtree(local_dir, ignore_errors=True) ok += 1 print(f"[{i}/{len(dirs)}] {name} ✓ → {cos_dest}(已删本地)") else: fail += 1 print(f"[{i}/{len(dirs)}] {name} ✗ 上传失败,保留本地: {err.strip()[:120]}") print(f"\n完成 — 成功: {ok} 失败: {fail} 跳过(无COS路径): {skip}") if __name__ == "__main__": main()