Communitygithub.com

叠帧 · 编号图片生成封面视频

将文件夹中纯数字命名的静态图片(如01.jpg、200.jpg)按编号排序,合成为MP4封面/预告视频,支持硬切或柔和淡入淡出过渡。

叠帧 · 编号图片生成封面视频 是什么?

该技能用于将文件夹中纯数字命名的图片序列(如01.jpg、02.jpg等,忽略logo、discord等非数字文件)转换为H.264编码的MP4封面/预告视频。它支持两种过渡方式:默认的淡入淡出(crossfade)和硬切(hard cut),并自动排序图片(按整数值而非字典序),处理编号不连续的情况。技能提供细致的参数控制,如每张图片时长、过渡时长、帧率、分辨率等,并包含防覆盖机制(自动备份已有输出)、输出验证步骤(检查时长、黑帧、最后一帧对比)、以及内存友好的分块渲染策略(默认每块6张,避免大视频渲染时内存溢出)。该技能适用于Claude Code等支持技能目录的AI代理工具,脚本位于 `scripts/imgseq2mp4.py`,依赖于ffmpeg,并处理了Windows环境下ffmpeg路径选择、颜色空间转换(全范围JPEG转有限范围bt709)等细节。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add LiliLIN0324/imgseq-cover-video-skill

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

叠帧 · 编号图片 → 封面视频

概述

扫描文件夹,仅保留文件名主干为纯数字的文件(01.jpg、200.jpg),按数字顺序播放,并编码为H.264 mp4。图片之间可选择硬切(--transition none)或淡入淡出(--transition fade,默认)。非数字命名的图片(logo、discord等)和已有视频将被忽略。

操作步骤

  1. 首先检查文件夹。 列出文件,并使用ffprobe探测一张图片的尺寸。记录有多少张编号图片以及宽高比是否混合。
  2. 备份已有输出。 如果<文件夹>/cover.mp4已存在,在渲染前将其重命名为cover.prev-YYYYMMDD.mp4。切勿静默覆盖用户之前的渲染结果。
  3. 使用内置脚本渲染:
python "<技能目录>/scripts/imgseq2mp4.py" --dir "<文件夹>" --out cover.mp4

默认值:每张图片0.8秒,0.2秒淡入淡出过渡,30 fps,1920x1080,黑边填充,CRF 18,无音频,+faststart。

  1. 验证,不要猜测。 探测时长/帧数,确认无黑帧,并提取最后一帧与最后一张源图片对比:
ffprobe -v error -show_entries format=duration -show_entries stream=nb_frames -of default=nw=1 cover.mp4
ffmpeg -i cover.mp4 -vf blackdetect=d=0.05:pix_th=0.10 -an -f null -
ffmpeg -y -sseof -0.05 -i cover.mp4 -frames:v 1 frame_last.png

当启用过渡时,还需在第一个过渡窗口内抓取一帧,检查是否为混合帧(更接近图片2而非硬切结果,但仍与两个源有可测量的差异)。

  1. 报告 图片数量、忽略的图片、总时长、输出路径和大小。

节奏

总时长 = n × 秒数 − (n−1) × 过渡秒数。每张图片的呈现场步长为 秒数 − 过渡秒数;观众感受到的是这个步长,而非 --seconds。

每张图片步长命令20张图44张图200张图
0.35 秒--seconds 0.5 --transition-seconds 0.15~8 秒~18 秒~75 秒
0.45 秒--seconds 0.65 --transition-seconds 0.2~9 秒~22 秒~95 秒
0.60 秒(默认)--seconds 0.8 --transition-seconds 0.2~12 秒~27 秒~120 秒
0.80 秒--seconds 1.0 --transition-seconds 0.2~16 秒~34 秒~150 秒

硬切使用 --transition none --seconds <步长>。

当用户要求更快或更慢时,逐行调整。保持 --transition-seconds 在0.15–0.2;更长的过渡会让人感觉像幻灯片而非淡入淡出。

规则

  • 仅使用淡入淡出。不要使用滑动、擦除或其他推进过渡——这些已被拒绝。
  • 选择正则表达式 ^\d+\.(jpe?g|png|webp)$ — 文件名必须仅为数字。这排除了 logo.jpg、discord.jpg、cover.jpg。
  • 按整数值排序,而非字典序(2.jpg 在 10.jpg 之前,99.jpg 在 100.jpg 之前)。编号不连续是可接受的;缺失编号不是错误。
  • 使用 --fit pad(默认)以保持整个帧可见。仅当用户明确要求边缘到边缘裁剪时才使用 --fit fill。
  • 输出无声。除非用户提供音轨,否则不要添加音乐。
  • 保持颜色不变。JPEG是全范围的;如果将其编码为未标记的全范围H.264,大多数播放器会解码为有限范围,导致结果看起来更亮且洗白(+10个级别)。脚本会转换为有限范围bt709并进行标记——不要“简化”该处理链。
  • 脚本拒绝在未使用 --force 时覆盖 --out;通过备份解决,而非盲目强制。

机器说明

  • ffmpeg不在PATH中。脚本优先使用真正的 ffmpeg.exe(~/.dsh/tools/ffmpeg/**/ffmpeg.exe,然后是 C:/ 或 D:/ffmpeg 下的副本),再考虑任何 .cmd 存根,因为存根通过cmd.exe路由并限制命令行长度约8k字符。可通过 FFMPEG=/path/to/ffmpeg 覆盖。
  • 此构建缺少 -filter_complex_script;通过 -filter_complex 内联传递xfade图(脚本已如此实现)。
  • 过渡按 --chunk(默认6)分组渲染,然后合并,因此最多同时打开6个解码器。在16 GB机器上,单次44输入xfade传递会耗尽RAM(剩余约2.4 GB)并失败,错误为 Cannot allocate memory;在此不要将 --chunk 提高到8以上。分组是递归的,因此200张图分三个阶段合并,不会内存不足。
  • 中间阶段文件使用CRF 14 / veryfast编码并丢弃;只有最终传递使用 --crf / medium。
  • 中间帧需要可写目录。tempfile.mkdtemp() 的结果在受限沙箱下可能不可访问(在Windows + DSH上观察到:ffmpeg报 Permission denied,os.listdir 抛出 WinError 5)。因此脚本创建一个普通目录,验证其可写性,并通过 $IMGSEQ_WORKDIR → 系统临时目录 → <输出目录>/.imgseq-work 进行回退。

资源

  • scripts/imgseq2mp4.py — 选择、数值排序、硬切或淡入淡出渲染、便于验证的摘要。

相关技能