name: cover-gen description: | 社交媒体封面生成 + 视频首帧插入。从视频成片提取关键帧,按各平台规格 AI 生成封面, 最终将封面作为视频第一帧(0.1秒)合成到视频中。底层使用 media_gen (Gemini/OpenAI) + FFmpeg。 触发词:封面、cover、生成封面、封面制作、首帧、cover gen、thumbnail、视频封面。
封面生成 + 视频首帧插入
功能
- 提取关键帧:从视频中截取参考帧用于风格指导
- 平台适配:按目标平台规格(尺寸、比例、文字规范)生成封面
- AI 生成:通过 media_gen 工具(Gemini/OpenAI)生成封面图片
- 首帧合成:将封面作为视频第一帧(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字+描边, 可高文字密度, 【分类】标注 |
| 1920x1080 | 16:9 | landscape |
英文标题, 专业风格 | |
| 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 提供文案 + 封面 promptadapters/{platform}.yamlCDP 自动发布
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
注意事项
- 封面图片和视频分辨率比例不一致时,会自动居中 + 黑边填充
- 0.1 秒在 30fps 下约为 3 帧,60fps 下约为 6 帧
- concat 协议要求所有片段编码参数一致(codec、分辨率、帧率、pix_fmt)
- 如果原视频有音频轨道,封面片段必须包含静音音轨
- 大分辨率视频(4K)建议先用 1080p 测试效果