with one click
videocut
口播视频转录和口误识别。生成审查稿和删除任务清单。触发词:剪口播、处理视频、识别口误
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
口播视频转录和口误识别。生成审查稿和删除任务清单。触发词:剪口播、处理视频、识别口误
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| name | videocut:剪口播 |
| description | 口播视频转录和口误识别。生成审查稿和删除任务清单。触发词:剪口播、处理视频、识别口误 |
火山引擎转录 + AI 口误识别 + 网页审核
用户: 帮我剪这个口播视频
用户: 处理一下这个视频
output/
└── YYYY-MM-DD_视频名/
├── 剪口播/
│ ├── 1_转录/
│ │ ├── audio.mp3
│ │ ├── volcengine_result.json
│ │ └── subtitles_words.json
│ ├── 2_分析/
│ │ ├── readable.txt
│ │ ├── auto_selected.json
│ │ └── 口误分析.md
│ └── 3_审核/
│ └── review.html
└── 字幕/
└── ...
规则:已有文件夹则复用,否则新建。
0. 创建输出目录
↓
1. 提取音频 (ffmpeg)
↓
2. 上传获取公网 URL (uguu.se)
↓
3. 火山引擎 API 转录
↓
4. 生成字级别字幕 (subtitles_words.json)
↓
5. AI 分析口误/静音,生成预选列表 (auto_selected.json)
↓
6. 生成审核网页 (review.html)
↓
7. 启动审核服务器,用户网页确认
↓
【等待用户确认】→ 网页点击「执行剪辑」或手动 /剪辑
↓
8. 执行剪辑 (cut_video.ps1)
↓
9. 【可选】导出到剪映草稿 (-ExportToJianying)
# 变量设置(根据实际视频调整)
VIDEO_PATH="/path/to/视频.mp4"
VIDEO_NAME=$(basename "$VIDEO_PATH" .mp4)
DATE=$(date +%Y-%m-%d)
BASE_DIR="output/${DATE}_${VIDEO_NAME}/剪口播"
# 创建子目录
mkdir -p "$BASE_DIR/1_转录" "$BASE_DIR/2_分析" "$BASE_DIR/3_审核"
cd "$BASE_DIR"
cd 1_转录
# 1. 提取音频(文件名有冒号需加 file: 前缀)
ffmpeg -i "file:$VIDEO_PATH" -vn -acodec libmp3lame -y audio.mp3
# 2. 上传获取公网 URL
curl -s -F "files[]=@audio.mp3" https://uguu.se/upload
# 返回: {"success":true,"files":[{"url":"https://h.uguu.se/xxx.mp3"}]}
# 3. 调用火山引擎 API
SKILL_DIR="/Users/chengfeng/Desktop/AIos/剪辑Agent/.claude/skills/剪口播"
"$SKILL_DIR/scripts/volcengine_transcribe.sh" "https://h.uguu.se/xxx.mp3"
# 输出: volcengine_result.json
node "$SKILL_DIR/scripts/generate_subtitles.js" volcengine_result.json
# 输出: subtitles_words.json
cd ..
cd 2_分析
node -e "
const data = require('../1_转录/subtitles_words.json');
let output = [];
data.forEach((w, i) => {
if (w.isGap) {
const dur = (w.end - w.start).toFixed(2);
if (dur >= 0.5) output.push(i + '|[静' + dur + 's]|' + w.start.toFixed(2) + '-' + w.end.toFixed(2));
} else {
output.push(i + '|' + w.text + '|' + w.start.toFixed(2) + '-' + w.end.toFixed(2));
}
});
require('fs').writeFileSync('readable.txt', output.join('\\n'));
"
先读 用户习惯/ 目录下所有规则文件。
必须先分句,再分析。按静音切分成句子列表:
node -e "
const data = require('../1_转录/subtitles_words.json');
let sentences = [];
let curr = { text: '', startIdx: -1, endIdx: -1 };
data.forEach((w, i) => {
const isLongGap = w.isGap && (w.end - w.start) >= 0.5;
if (isLongGap) {
if (curr.text.length > 0) sentences.push({...curr});
curr = { text: '', startIdx: -1, endIdx: -1 };
} else if (!w.isGap) {
if (curr.startIdx === -1) curr.startIdx = i;
curr.text += w.text;
curr.endIdx = i;
}
});
if (curr.text.length > 0) sentences.push(curr);
sentences.forEach((s, i) => {
console.log(i + '|' + s.startIdx + '-' + s.endIdx + '|' + s.text);
});
" > sentences.txt
node -e "
const words = require('../1_转录/subtitles_words.json');
const selected = [];
words.forEach((w, i) => {
if (w.isGap && (w.end - w.start) >= 0.5) selected.push(i);
});
require('fs').writeFileSync('auto_selected.json', JSON.stringify(selected, null, 2));
console.log('≥0.5s静音数量:', selected.length);
"
→ 输出 auto_selected.json(只含静音 idx)
检测规则(按优先级):
| # | 类型 | 判断方法 | 删除范围 |
|---|---|---|---|
| 1 | 重复句 | 相邻句子开头≥5字相同 | 较短的整句 |
| 2 | 隔一句重复 | 中间是残句时,比对前后句 | 前句+残句 |
| 3 | 残句 | 话说一半+静音 | 整个残句 |
| 4 | 句内重复 | A+中间+A 模式 | 前面部分 |
| 5 | 卡顿词 | 那个那个、就是就是 | 前面部分 |
| 6 | 重说纠正 | 部分重复/否定纠正 | 前面部分 |
| 7 | 语气词 | 嗯、啊、那个 | 标记但不自动删 |
核心原则:
分段分析(循环执行):
1. Read readable.txt offset=N limit=300
2. 结合 sentences.txt 分析这300行
3. 追加口误 idx 到 auto_selected.json
4. 记录到 口误分析.md
5. N += 300,回到步骤1
🚨 关键警告:行号 ≠ idx
readable.txt 格式: idx|内容|时间
↑ 用这个值
行号1500 → "1568|[静1.02s]|..." ← idx是1568,不是1500!
口误分析.md 格式:
## 第N段 (行号范围)
| idx | 时间 | 类型 | 内容 | 处理 |
|-----|------|------|------|------|
| 65-75 | 15.80-17.66 | 重复句 | "这是我剪出来的一个案例" | 删 |
在 .agent/skills/.env 中配置以下关键路径和密钥:
| 配置项 | 说明 | 示例值 |
|---|---|---|
VOLCENGINE_API_KEY | 火山引擎 API Key | your_api_key_here |
RAW_VIDEO_DIR | 原始视频存放目录 | F:\Focusee\Video |
JIANYING_DRAFT_DIR | 剪映草稿存放目录 | E:\剪映草稿\JianyingPro Drafts |
注意:脚本在导出剪映时,会优先从
RAW_VIDEO_DIR寻找原始视频以保证同步精度。
cd ../3_审核
# 6. 生成审核网页
node "$SKILL_DIR/scripts/generate_review.js" ../1_转录/subtitles_words.json ../2_分析/auto_selected.json ../1_转录/audio.mp3
# 输出: review.html
# 7. 启动审核服务器
node "$SKILL_DIR/scripts/review_server.js" 8899 "$VIDEO_PATH"
# 打开 http://localhost:8899
用户在网页中:
[
{"text": "大", "start": 0.12, "end": 0.2, "isGap": false},
{"text": "", "start": 6.78, "end": 7.48, "isGap": true}
]
[72, 85, 120] // Claude 分析生成的预选索引
cd F:\dai ma\剪辑\.agent\skills
cp .env.example .env
# 编辑 .env 填入 VOLCENGINE_API_KEY=xxx
剪辑完成后,可以将结果导出到剪映草稿,方便进行二次编辑。
为了实现从自动化剪辑到剪映二次创作的无缝衔接,必须遵循以下“最佳实践”以保证音画同步和极佳的初剪体验。
禁止:将剪辑后的成品 mp4 导入剪映。这会导致字幕出现毫秒级的累积位移。
推荐:使用原始长视频素材,配合 keep_segments.json。通过 Python 脚本在剪映草稿中将原始视频切成段并“接起来”。
为了让字幕看起来“像人写的”,必须放弃简单的字数统计(如每12字一断),改用以下优先级逻辑:
isGap (停顿 > 0.3s) 作为第一断句点。TextSegment(文本片段),因为难以批量修改样式。script.import_srt() 接口,将生成的 SRT 文件导入为剪映原生的“字幕轨道”。transform_y = -0.8。pip install pyJianYingDraft。JianyingPro Drafts/
└── [草稿名称]/
├── draft_content.json # 由脚本生成
└── draft_meta_info.json # 必须存在,否则剪映无法加载
# 建议通过 cut_video.ps1 自动触发
./cut_video.ps1 -VideoPath "..." -ExportToJianying
--drafts-folder, -d: 剪映草稿目录(默认:E:\剪映草稿\JianyingPro Drafts)[
{"start": 0.0, "end": 5.5},
{"start": 8.2, "end": 15.0}
]