原片
2,480条
Share 1988 + Windows 492
DJI / Osmo Action 素材的自动剪辑流水线 — 设备插上即同步、AI 打分挑废片、按时间聚类成故事、Web 浏览、再吐成剪映草稿。 架构清晰、数据健全、跑得起来;问题主要在边角的工程化:实验脚本散在根目录、单文件 SPA 撑到 1016 行、若干 flag 字段漏写。
一句话:DJI 飞行记录仪的"按 Enter 就出片"工具。 后端是一坨 Python 脚本 (pipeline / stories / smart_picker / build_jianying_draft) 各管一截, 中间用 Flask (port 8902) 把 JSON 暴露出来, 前端是一个 Vite + React 19 的 SPA (port 5173) 把上千段视频塞进虚拟滚动网格。 剪映草稿 / FCPXML / 直接 ffmpeg 拼成片 — 三条出口都有,作者自己挑顺手的用。
~/bin/dji-sync.shrsync 到 /Volumes/Share/DCIM/DJI_001/ (MP4) + /preview/ (LRF)--video-dir 只保留最后一个值。/api/results /api/stories /api/stats /api/thumbnail/<f> /api/video/<f> /api/sync-log。CORS 全开,单机自用。App.tsx 一个 1016 行的大文件里。Tailwind v4 + shadcn/ui + lucide-react,@tanstack/react-virtual 撑住 2k+ 视频网格。force dark mode。/Volumes/*/DCIM/DJI_001,大小写不敏感去重,rsync 到 Share 盘。带文件锁防并发。output/cuts/NN_*_highlight.mp4 按序拼成剪映草稿,加 BGM 和转场。依赖 ~/.openclaw/workspace/projects/CapCutAPI (pyJianYingDraft),路径硬编码。output/*.fcpxml。最近一次跑是 3 月。draw_text_advanced{,2,3}.py draw_text_srt.py render_video{,_stable,_list}.py test_*.py debug_*.py fix_*.py — 都是 3 月的字幕烧录 / 渲染迭代实验,作者已经不动了。legacy/ 文件夹
根目录现在塞着 14 个 3 月写的 draw_text_*/render_video*/test_*/debug_*/fix_*,每次打开项目都得在 mtime 里大海捞针确认哪个是当前在用的。
results.json.bak.* 备份
output/ 里躺着 5 个一模一样大小 (~1 MB) 的 .bak,加起来 5 MB,fix_meta / rollback 脚本留下的。git 又不进库,纯占地。
pipeline.py 的 --video-dir argparse bug
CLAUDE.md 自己都标了:nargs='+' 写法下重复传 --video-dir 只保留最后一个。等于一个一直在咬人的脚趾绊。
action='append' + 内部 flatten,5 行改动。以后多盘并行扫描不用拆三个命令、不用心算断点续传冲突。gpt4o_analyzed=True 这一行赋值
results.json 里 2,097 条有 ai_score,但只有 9 条带 gpt4o_analyzed=true。/api/stats 显示 "已分析 9 条",前端 stats 完全看不出真实覆盖率。
item['gpt4o_analyzed']=True。一次性补历史数据:for x in d: x['gpt4o_analyzed']=bool(x.get('ai_score'))。/api/stats 立刻好看,前端的 dashboard 才有意义。run_highlights.py 的日期改成 CLI 参数
每次想给某一段日子补 highlight 就得改源码、保存、跑、记得改回来。CLAUDE.md 里都警告了"日期硬编码在 main() 里"。
--from / --to 两个 argparse 参数,默认值保留当前的硬编码区间。十几行改动,以后写 shell alias 就能跑。video_path 改成"按 filename 反查",别再存绝对路径
现在 results.json 里 2,158 条全是 /Volumes/Share/DCIM/... 或 /Volumes/Windows/preview/... 的绝对路径。盘换名 / 不挂 → /api/video/* 全 404。
App.tsx 的 1,016 行拆 3 个组件
单文件 SPA 已经撑不住:state、grid、filter bar、video player、stories drawer 全在一个 module 里。改任何一处都要重读全文。
VideoGrid.tsx / StoryDrawer.tsx / FilterBar.tsx 三个就够。state 仍然留在 App.tsx,通过 props 传 — 不引 zustand/redux,保持作者偏好的最小依赖。重构后单文件控制在 ~300 行。POST /api/clip-status 写入接口
前端的"标记 selected"现在是个假按钮 — server.py 没有任何写入路由,刷新就丢。clip_status 字段空有其表。
~/Library/LaunchAgents/com.leway.dji-sync.plist),今天最新一次同步在 12:14 完成:MP4 +265, LRF +265, skip 0。日志 80 KB,SD 卡上的素材已落到 Share。gpt4o_analyzed flag 历史漏写 — 2,097 条有 ai_score、只有 9 条带 flag,导致 /api/stats 显示"已分析 9 条"误报。实际覆盖率 97%,数据是好的,只是统计字段坏了。curl localhost:5173 返回 HTML、dark 模式 class 已加。后端 /api/results /api/stories /api/stats 三条每分钟被轮询一次 (server.log 里看得到),延迟稳定 200。/api/video/DJI_20260131205739_0163_D.mp4 返回 200, 273 MB, video/mp4。ffprobe 抽 cuts 任意一段 duration=4.01 s,文件完整。前提是 /Volumes/Share 挂着。~/.openclaw/workspace/projects/CapCutAPI 路径硬编码,换机器没有 symlink 会直接 import 失败。ai_score is not None 判定;gpt4o_analyzed=True 字段只有 9 条,但那是字段漏写的 bug (见 Chapter 2 / Item 04)。