cover-gen

star 161

社交媒体封面生成 + 视频首帧插入。从视频成片提取关键帧,按各平台规格 AI 生成封面, 最终将封面作为视频第一帧(0.1秒)合成到视频中。底层使用 media_gen (Gemini/OpenAI) + FFmpeg。 触发词:封面、cover、生成封面、封面制作、首帧、cover gen、thumbnail、视频封面。

npc-live By npc-live schedule Updated 5/31/2026

name: cover-gen description: | 社交媒体封面生成 + 视频首帧插入。从视频成片提取关键帧,按各平台规格 AI 生成封面, 最终将封面作为视频第一帧(0.1秒)合成到视频中。底层使用 media_gen (Gemini/OpenAI) + FFmpeg。 触发词:封面、cover、生成封面、封面制作、首帧、cover gen、thumbnail、视频封面。

封面生成 + 视频首帧插入

功能

  1. 提取关键帧:从视频中截取参考帧用于风格指导
  2. 平台适配:按目标平台规格(尺寸、比例、文字规范)生成封面
  3. AI 生成:通过 media_gen 工具(Gemini/OpenAI)生成封面图片
  4. 首帧合成:将封面作为视频第一帧(0.1秒),用 FFmpeg concat 合成

工作流概览

输入:视频成片 + 平台信息
  ↓
Step 1: 提取视频关键帧 + 技术参数 (ffprobe/ffmpeg)
  ↓
Step 2: 确定平台封面规格(尺寸、比例、文字规范)
  ↓
Step 3: AI 生成封面 (media_gen)
  ↓
Step 4: 封面合成到视频第一帧 — 0.1s (ffmpeg concat)
  ↓
输出:带封面首帧的视频 + 独立封面图

Step 1: 提取视频信息 + 关键帧

从原始视频中获取技术参数和关键帧,用于指导封面生成。

# 获取视频分辨率、帧率、时长
ffprobe -v error \
  -select_streams v:0 \
  -show_entries stream=width,height,r_frame_rate,codec_name \
  -show_entries format=duration \
  -of json \
  "$VIDEO_PATH"

# 截取关键帧(0s, 3s, 中间帧)作为参考
ffmpeg -y -i "$VIDEO_PATH" \
  -vf "select='eq(n\,0)+eq(n\,90)+eq(n\,$(echo "$TOTAL_FRAMES/2" | bc))',setpts=N/FRAME_RATE/TB" \
  -frames:v 3 -q:v 2 \
  "/tmp/cover_ref_frame_%d.jpg"

输出:

  • width, height, fps, duration — 视频技术参数
  • cover_ref_frame_1.jpg ~ cover_ref_frame_3.jpg — 关键帧参考图

Step 2: 平台封面规格

根据目标发布平台确定封面规格:

平台 尺寸 比例 media_gen size 文字规范
抖音 1080x1440 3:4 portrait_3x4 ≤8字大标题, 高对比度, 人脸+30% CTR
抖音(竖) 1080x1920 9:16 portrait 同上
小红书 1080x1440 3:4 portrait_3x4 ≤10字, 关键信息可视化
B站 1920x1080 16:9 landscape ≤12字+描边, 可高文字密度, 【分类】标注
LinkedIn 1920x1080 16:9 landscape 英文标题, 专业风格
Twitter 1600x900 16:9 landscape 简洁大字, 品牌色
YouTube 1280x720 16:9 landscape ≤10字, 高饱和度

详见各平台 SKILL.md 的封面规范章节:

  • social-publish/douyin/SKILL.md — 封面规范
  • social-publish/xiaohongshu/SKILL.md — 封面设计要点
  • social-publish/bilibili/SKILL.md — 封面规范

Step 3: AI 生成封面

内置工具 media_gen,直接调用:

{
  "prompt": "封面描述...",
  "size": "portrait",
  "output": "~/Desktop/cover_20260415.png"
}
  • provider 和 model 在 config.yml tools.media_gen 中配置
  • 支持的尺寸:portrait (9:16), landscape (16:9), landscape_4x3 (4:3), square (1:1)

推荐模型

使用 GPT Image 2(gpt-image-2)生成封面——它能准确渲染中英文文字。 Gemini 对中文文字渲染不稳定,容易出现文字缺失或乱码。

在 config.yml 中配置:

tools:
  media_gen:
    platform: openai
    model: gpt-image-2

封面 prompt 模板

关键规则:prompt 中必须明确指定要渲染的文字内容。

Design a video cover image for {平台}.

Topic: {title}
Key selling points: {desc中的关键信息}

TEXT OVERLAY (must appear exactly as written):
- Main title: "{≤N字标题}" — large bold text, centered, with dark stroke/shadow for readability
- Optional subtitle: "{副标题}" — smaller text below the title

Visual requirements:
- Aspect ratio: {平台对应尺寸}
- Style: {平台风格}
- Background: clean, not cluttered, complementary to the text
- Subject/product prominently displayed
- Key numbers or benefits visualized
- High contrast between text and background

The text MUST be clearly readable and rendered accurately — do not omit or alter any characters.

使用示例(B站横屏):

Design a video cover image for Bilibili.

Topic: AI时代的终端新玩法
Key selling points: AI terminal tools, productivity boost, modern workflow

TEXT OVERLAY (must appear exactly as written):
- Main title: "AI时代的终端新玩法" — large bold text with white stroke outline, centered
- Category tag: "【教程】" — top-left corner badge

Visual requirements:
- Aspect ratio: 16:9 landscape (1920x1080)
- Style: tech/futuristic, dark background with neon accent colors
- Terminal/code editor interface elements in the background
- AI neural network visual elements
- High contrast between text and background

The text MUST be clearly readable and rendered accurately — do not omit or alter any characters.

Step 4: 封面合成到视频第一帧 (0.1s)

生成的封面插入为视频的第一帧,持续 0.1 秒,然后紧接原始视频。

完整 ffmpeg 命令

#!/bin/bash
# 输入参数
COVER_IMAGE="$1"   # 封面图片路径
VIDEO_INPUT="$2"   # 原始视频路径
VIDEO_OUTPUT="$3"  # 输出视频路径

# Step 4a: 获取原视频的分辨率、帧率和 timescale
eval $(ffprobe -v error -select_streams v:0 \
  -show_entries stream=width,height,r_frame_rate,time_base \
  -of default=noprint_wrappers=1 "$VIDEO_INPUT")
FPS=$(echo "$r_frame_rate" | bc -l | xargs printf "%.0f")
TIMESCALE=$(echo "$time_base" | sed 's|1/||')

# Step 4b: 将封面图片转为 0.1 秒的视频片段
# 匹配原视频的分辨率、帧率、编码和 timescale,确保无缝拼接
# ⚠️ -video_track_timescale 必须匹配原视频,否则 concat -c copy 会导致画面加速
ffmpeg -y \
  -loop 1 -i "$COVER_IMAGE" \
  -t 0.1 \
  -vf "scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black" \
  -r "$FPS" \
  -c:v libx264 -preset fast -crf 18 \
  -pix_fmt yuv420p \
  -video_track_timescale "$TIMESCALE" \
  "/tmp/cover_clip.mp4"

# Step 4c: 统一原视频编码格式(确保 concat 兼容)
ffmpeg -y \
  -i "$VIDEO_INPUT" \
  -c:v libx264 -preset fast -crf 18 \
  -pix_fmt yuv420p \
  -r "$FPS" \
  -video_track_timescale "$TIMESCALE" \
  -c:a aac -b:a 128k \
  "/tmp/video_normalized.mp4"

# Step 4d: 使用 concat 协议拼接(封面片段 + 原视频)
cat > /tmp/concat_list.txt << EOF
file '/tmp/cover_clip.mp4'
file '/tmp/video_normalized.mp4'
EOF

ffmpeg -y \
  -f concat -safe 0 \
  -i /tmp/concat_list.txt \
  -c copy \
  "$VIDEO_OUTPUT"

# 清理临时文件
rm -f /tmp/cover_clip.mp4 /tmp/video_normalized.mp4 /tmp/concat_list.txt

echo "Done: $VIDEO_OUTPUT"

简化版(原视频已是 H.264/yuv420p 时)

如果原视频已经是标准 H.264 编码,可以跳过重编码:

# 封面 → 0.1s 视频(匹配原视频参数 + timescale)
ffmpeg -y -loop 1 -i "$COVER_IMAGE" \
  -t 0.1 \
  -vf "scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black" \
  -r "$FPS" -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p \
  -video_track_timescale "$TIMESCALE" \
  -an \
  "/tmp/cover_clip.mp4"

# 拼接
cat > /tmp/concat_list.txt << EOF
file '/tmp/cover_clip.mp4'
file '$VIDEO_INPUT'
EOF

ffmpeg -y -f concat -safe 0 -i /tmp/concat_list.txt -c copy "$VIDEO_OUTPUT"

带音频处理的版本

如果原视频有音频轨道,封面片段需要添加静音音轨才能使用 concat 协议:

# 封面 → 0.1s 视频 + 静音音轨(匹配 timescale)
ffmpeg -y -loop 1 -i "$COVER_IMAGE" \
  -f lavfi -i anullsrc=r=44100:cl=stereo \
  -t 0.1 \
  -vf "scale=${width}:${height}:force_original_aspect_ratio=decrease,pad=${width}:${height}:(ow-iw)/2:(oh-ih)/2:black" \
  -r "$FPS" -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p \
  -video_track_timescale "$TIMESCALE" \
  -c:a aac -b:a 128k \
  -shortest \
  "/tmp/cover_clip.mp4"

关键参数说明

参数 说明
-loop 1 将静态图片循环为视频流
-t 0.1 持续 0.1 秒(约 3 帧 @30fps)
scale=W:H 匹配原视频分辨率
pad=W:H 居中填充黑边(当比例不一致时)
-r $FPS 匹配原视频帧率
-pix_fmt yuv420p 标准像素格式,确保 concat 兼容
-video_track_timescale 必须匹配原视频的 timescale,否则 concat copy 会导致画面加速
-crf 18 高质量编码
-c copy concat 阶段零损耗拷贝

与上下游对接

上游(视频来源)

  • video-stitcher 的最终成片
  • 用户直接提供的原始视频
  • digital-avatar 生成的数字人视频

下游(发布渠道)

  • social-publish/{platform} 平台 Skill 提供文案 + 封面 prompt
  • adapters/{platform}.yaml CDP 自动发布

Pipeline 集成

video-skills/video-stitcher → 视频成片
        ↓
social-publish/{platform}/SKILL.md → 文案 + 封面 prompt
        ↓
cover-gen (media_gen) → 封面图片
        ↓
cover-gen (ffmpeg concat) → 带封面首帧的视频
        ↓
adapters/{platform}.yaml (CDP) → 自动发布

与 daily-content.whip 对接

daily-content.whip 内容创作完成后、daily-publish.whip 发布之前:

daily-content.whip → 文案草稿 (status=approved)
        ↓
cover-gen (media_gen) → 各平台封面
        ↓
cover-gen (ffmpeg) → 视频 + 封面首帧
        ↓
daily-publish.whip → 发布

与 media.whip (抖音爆款) 对接

media.whip Phase 5h 视频汇总后新增:

Phase 5h: 视频汇总 → final video
        ↓
Phase 5i: 封面生成 (media_gen, 参考尾帧/关键帧)
        ↓
Phase 5j: 封面 → 视频首帧 (ffmpeg, 0.1s)
        ↓
Phase 6: 发布/总结

多平台批量封面 + 首帧示例

为同一个视频生成多平台封面并各自合成首帧:

#!/bin/bash
VIDEO="./final_video.mp4"
TITLE="AI帮你找人脉"

# 获取视频参数
eval $(ffprobe -v error -select_streams v:0 \
  -show_entries stream=width,height,r_frame_rate \
  -of default=noprint_wrappers=1 "$VIDEO")

# 截取参考帧
ffmpeg -y -i "$VIDEO" -vf "select=eq(n\,90)" -frames:v 1 -q:v 2 /tmp/ref_frame.jpg

# 抖音版封面(竖屏 3:4)— 调用内置 media_gen 工具
# {"prompt":"为抖音制作视频封面。主题:$TITLE。大字标题,高对比度,人物突出,竖屏3:4比例","size":"portrait","output":"/tmp/cover_douyin.png"}

# B站版封面(横屏 16:9)— 调用内置 media_gen 工具
# {"prompt":"为B站制作视频封面。主题:$TITLE。【教程】标签,大字标题+描边,横屏16:9比例","size":"landscape","output":"/tmp/cover_bilibili.png"}

# 为每个平台合成首帧
for PLATFORM in douyin bilibili; do
  COVER="/tmp/cover_${PLATFORM}.png"
  OUTPUT="./final_${PLATFORM}.mp4"

  case $PLATFORM in
    douyin)   W=1080; H=1920 ;;
    bilibili) W=1920; H=1080 ;;
  esac

  # 封面 → 0.1s 片段(含静音音轨)
  ffmpeg -y -loop 1 -i "$COVER" \
    -f lavfi -i anullsrc=r=44100:cl=stereo \
    -t 0.1 -vf "scale=${W}:${H}:force_original_aspect_ratio=decrease,pad=${W}:${H}:(ow-iw)/2:(oh-ih)/2:black" \
    -r 30 -c:v libx264 -preset fast -crf 18 -pix_fmt yuv420p \
    -c:a aac -b:a 128k -shortest \
    "/tmp/cover_clip_${PLATFORM}.mp4"

  # 拼接
  echo "file '/tmp/cover_clip_${PLATFORM}.mp4'" > /tmp/concat_${PLATFORM}.txt
  echo "file '$(realpath $VIDEO)'" >> /tmp/concat_${PLATFORM}.txt
  ffmpeg -y -f concat -safe 0 -i /tmp/concat_${PLATFORM}.txt -c copy "$OUTPUT"

  echo "Done: $OUTPUT"
done

注意事项

  1. 封面图片和视频分辨率比例不一致时,会自动居中 + 黑边填充
  2. 0.1 秒在 30fps 下约为 3 帧,60fps 下约为 6 帧
  3. concat 协议要求所有片段编码参数一致(codec、分辨率、帧率、pix_fmt)
  4. 如果原视频有音频轨道,封面片段必须包含静音音轨
  5. 大分辨率视频(4K)建议先用 1080p 测试效果
Install via CLI
npx skills add https://github.com/npc-live/clawfirm --skill cover-gen
Repository Details
star Stars 161
call_split Forks 12
navigation Branch main
article Path SKILL.md
More from Creator