Skill: liuhedev/lh-video-gen (version 1.0.0)

--- name: lh-video-gen description: Generate vertical short videos (9:16) from a Markdown script. Parses script sections, generates TTS audio, renders subtitle cards, and composites into MP4 with FFmpeg. homepage: https://github.com/liuhedev/lh-openclaw-kit --- # Video-Gen Skill 从视频脚本 Markdown 文件一键生成竖版短视频（9:16）。 **核心思路：以图定音** - 每段脚本的画面说明 -> 字幕卡片图 - 每段口播文案 -> TTS 配音 - 每张图展示时长 = 对应音频时长，音画天然同步 ## 快速开始 ```bash python3 generate.py script.md -o output.mp4 ``` ### 使用预制图片（跳过 Chrome 截图） ```bash python3 generate.py script.md --images-dir ./my-slides -o output.mp4 ``` 图片命名规则：`slide_01.png`, `slide_02.png`...，与脚本分段一一对应。 ### 自定义 TTS 命令 ```bash python3 generate.py script.md --tts-command "my-tts {text} -o {output} -v {voice} -r {rate}" ``` 占位符：`{text}` 口播文案、`{output}` 输出路径、`{voice}` 音色、`{rate}` 语速。 ## 参数说明 ``` python3 generate.py <脚本路径> [选项] 选项： -o, --output 输出 MP4 路径（默认：tmp/video-output.mp4） -v, --voice TTS 音色（默认：zh-CN-YunxiNeural） -r, --rate 语速（默认：+0%，如 +10%、-10%） -w, --width 视频宽度（默认：1080） --height 视频高度（默认：1920，9:16） --images-dir 使用已有图片目录，跳过 Chrome 截图 --tts-command 自定义 TTS 命令模板（占位符：{text} {output} {voice} {rate}） --keep-temp 保留临时文件（图片、音频、片段） --no-subs 不烧录字幕 ``` ## 依赖 ### 系统依赖 - **FFmpeg**：视频合成（`brew install ffmpeg`） - **Chrome**：HTML 截图（仅在未使用 `--images-dir` 时需要） - 自动检测 macOS/Linux 常见路径，或通过 `CHROME_PATH` 环境变量指定 ### 推荐搭配的 Skill 以下 Skill 非必需，但搭配使用效果更佳： - **lh-edge-tts**：TTS 配音生成。自动检测同级目录 `../lh-edge-tts/scripts/tts_converter.py`，或通过 `EDGE_TTS_PATH` 环境变量指定，或用 `--tts-command` 替换为任意 TTS 工具 - **lh-html-to-image**：如需自定义更复杂的字幕卡片，可用此 Skill 生成图片后通过 `--images-dir` 传入 ## 脚本格式 用 `---` 分隔各段，每段包含 `**口播**`、`**字幕**`、`**画面**` 字段： ```markdown # 视频标题 --- ## 开场 **画面**：场景描述 **口播**：TTS 配音文案 **字幕**：屏幕显示文字\n支持换行 --- ## 结尾 **画面**：场景描述 **口播**：TTS 配音文案 **字幕**：屏幕显示文字 ``` 完整模板：`templates/script-template.md` ## 工作流程 1. 解析脚本 Markdown，提取各分段 2. 每段口播 -> TTS 生成 mp3 3. 每段字幕 -> HTML 模板截图生成 9:16 图片（或从 `--images-dir` 加载） 4. 每张图 + 对应音频 -> FFmpeg 合成视频片段 5. 拼接所有片段 -> 输出 MP4

path: templates/script-template.md
content: # 视频标题

> 脚本设计规范：
> - 开场必带核心热词（如 OpenClaw、AI Agent 等），提升搜索权重
> - 结尾固定引导语："关注刘贺同学"
> - 总时长 30-40 秒（4 段为宜）
> - 每段字幕不超过 3 行，每行不超过 15 字

---

## 开场
**画面**：画面说明（用于装饰元素，如"龙虾哥头像 + 大标题"）
**口播**：开场口播（必须包含核心热词，1秒让观众知道主题）
**字幕**：开场字幕\n包含核心关键词

---

## 核心内容1
**画面**：画面说明
**口播**：口播文案
**字幕**：字幕文案\n支持多行

---

## 核心内容2
**画面**：画面说明
**口播**：口播文案
**字幕**：字幕文案

---

## 结尾
**画面**：关注引导页面
**口播**：我是龙虾哥，关注刘贺同学，下期见！
**字幕**：关注「刘贺同学」\n下期见！


path: templates/slide-ai-bg.html
content: <!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1080, height=1920">
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }

  html, body {
    width: 1080px;
    height: 1920px;
    overflow: hidden;
    font-family: "PingFang SC", "Noto Sans CJK SC", "Source Han Sans", "Microsoft YaHei", sans-serif;
  }

  .bg {
    position: absolute;
    inset: 0;
    background-image: url('{{BG_IMAGE}}');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
  }

  .overlay {
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(0,0,0,0.25) 0%,
      rgba(0,0,0,0.15) 40%,
      rgba(0,0,0,0.55) 75%,
      rgba(0,0,0,0.75) 100%
    );
  }

  .subtitle-wrap {
    position: absolute;
    bottom: 220px;
    left: 60px;
    right: 60px;
    text-align: center;
  }

  .subtitle {
    display: inline-block;
    color: #fff;
    font-size: 58px;
    font-weight: 700;
    line-height: 1.55;
    letter-spacing: 2px;
    text-shadow:
      0 2px 8px rgba(0,0,0,0.9),
      0 0 24px rgba(0,0,0,0.7),
      2px 2px 0 rgba(0,0,0,0.8),
      -2px -2px 0 rgba(0,0,0,0.8),
      2px -2px 0 rgba(0,0,0,0.8),
      -2px 2px 0 rgba(0,0,0,0.8);
  }

  .brand {
    position: absolute;
    top: 60px;
    right: 70px;
    display: flex;
    align-items: center;
    gap: 12px;
    background: rgba(0,0,0,0.45);
    border-radius: 40px;
    padding: 10px 22px;
    backdrop-filter: blur(8px);
  }

  .brand-emoji { font-size: 32px; }

  .brand-text {
    color: rgba(255,255,255,0.90);
    font-size: 26px;
    font-weight: 600;
    letter-spacing: 1px;
  }

  .index-badge {
    position: absolute;
    top: 60px;
    left: 70px;
    width: 64px;
    height: 64px;
    border-radius: 50%;
    background: rgba(255,80,0,0.85);
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    font-size: 30px;
    font-weight: 800;
  }
</style>
</head>
<body>
  <div class="bg"></div>
  <div class="overlay"></div>
  <div class="index-badge">{{INDEX}}</div>
  <div class="brand">
    <span class="brand-emoji">🦞</span>
    <span class="brand-text">龙虾哥</span>
  </div>
  <div class="subtitle-wrap">
    <span class="subtitle">{{SUBTITLE}}</span>
  </div>
</body>
</html>


Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)