Initial commit: skills library
- 70 skills with code and documentation - Add .gitignore (ignore __pycache__, output/, temp/, venv/) - Clean up test intermediates and caches
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: video-desc-generator
|
||||
description: 根据视频字幕文件自动生成适合各平台(视频号、抖音、小红书、B站)的视频简介文案。支持视频转录,输出标题+4平台简介到一个txt文件。
|
||||
---
|
||||
|
||||
# Video Desc Generator
|
||||
|
||||
根据视频字幕自动生成各平台适配的视频简介文案。
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
当用户需要以下操作时使用此技能:
|
||||
- 根据视频文件生成完整字幕(使用faster-whisper转录)
|
||||
- 根据字幕生成视频标题和4平台简介
|
||||
- 为视频生成多平台(视频号、抖音、小红书、B站)适配的文案
|
||||
|
||||
## 工作流程
|
||||
|
||||
### 步骤1:视频转录
|
||||
|
||||
1. **使用 faster-whisper 转录视频**,生成带时间戳的SRT
|
||||
2. **输出**:`{视频名}_transcribed.srt`
|
||||
|
||||
**调用命令**:
|
||||
```bash
|
||||
cd .opencode/skills/video-desc-generator/scripts
|
||||
"D:/ProgramData/anaconda3/envs/py312_cuda/python.exe" transcribe_and_merge.py "<视频文件夹路径>"
|
||||
```
|
||||
|
||||
**重要**:只使用转录版本(`_transcribed.srt`)生成简介,**不要合并**原有字幕。
|
||||
|
||||
### 步骤2:生成简介
|
||||
|
||||
1. 读取转录后的SRT字幕(`_transcribed.srt`)
|
||||
2. 分析内容提取核心知识点
|
||||
3. 生成标题和4平台适配文案
|
||||
4. 输出到一个txt文件(包含所有平台)
|
||||
|
||||
## 输出规范
|
||||
|
||||
**输出目录**:视频文件夹所在目录
|
||||
|
||||
**输出文件**:
|
||||
- `{视频名}_transcribed.srt` - 转录字幕
|
||||
- `{视频名}_简介.txt` - 包含标题+4平台简介
|
||||
|
||||
**简介文件格式**:
|
||||
```
|
||||
【标题】xxx
|
||||
|
||||
=== 视频号 ===
|
||||
【短标题】xxx(≤16字)
|
||||
文案(~20字,精简有力)
|
||||
#标签
|
||||
|
||||
=== 抖音 ===
|
||||
文案(80-120字,情绪化+行动引导)
|
||||
#标签
|
||||
|
||||
=== 小红书 ===
|
||||
文案(100-600字,干货感+结构清晰)
|
||||
#标签
|
||||
|
||||
=== B站 ===
|
||||
文案(~100字,知识感+SEO优化)
|
||||
#标签
|
||||
```
|
||||
|
||||
## 转录环境配置
|
||||
|
||||
**Python环境**:`D:\ProgramData\anaconda3\envs\py312_cuda\python.exe`
|
||||
|
||||
**依赖**:
|
||||
- faster-whisper
|
||||
- torch (CUDA版本)
|
||||
- ffmpeg
|
||||
|
||||
## 各平台规范(2024-2025)
|
||||
|
||||
### 1. 微信视频号
|
||||
- **短标题**:≤16字,用于搜索、话题、活动等场景
|
||||
- **描述上限**:1000字(1分钟以内),100字(1分钟以上)
|
||||
- **显示限制**:全屏模式下最多显示2行(约20字),超出折叠
|
||||
- **建议**:短标题≤16字,描述控制在20字以内
|
||||
|
||||
### 2. 抖音
|
||||
- **标题**:30字
|
||||
- **描述**:150字符,超过80字折叠
|
||||
- **最佳长度**:80-120字
|
||||
- **特点**:情绪化、前10-20字决定是否点击
|
||||
|
||||
### 3. 小红书
|
||||
- **标题**:20字以内
|
||||
- **描述**:短笔记≥100字
|
||||
- **特点**:干货感、真实体验
|
||||
|
||||
### 4. 哔哩哔哩(B站)
|
||||
- **标题**:60字以内,建议20-30字
|
||||
- **简介**:建议100字以内
|
||||
- **特点**:知识感、SEO优化
|
||||
|
||||
## 通用最佳实践
|
||||
|
||||
1. **前10字定生死**:核心信息和吸引力必须在前10-20字
|
||||
2. **数字+情绪词**:用数字具体化,用情绪词引发共鸣
|
||||
3. **互动引导**:设置问题或行动指令提升互动率
|
||||
4. **避免违禁词**:禁用"最""第一""绝对""震惊"等极限词
|
||||
|
||||
## 脚本位置
|
||||
|
||||
- 转录脚本:`.opencode/skills/video-desc-generator/scripts/transcribe_and_merge.py`
|
||||
|
||||
## 参考资料
|
||||
|
||||
详见 `references/platform_guidelines.md`
|
||||
@@ -0,0 +1,3 @@
|
||||
# Example Reference
|
||||
|
||||
This is an example reference file. Delete if not needed.
|
||||
@@ -0,0 +1,197 @@
|
||||
# 各平台视频简介规范(2024-2025)
|
||||
|
||||
## 一、微信视频号
|
||||
|
||||
### 字数限制
|
||||
|
||||
| 视频时长 | 文案上限(含话题和@) |
|
||||
|---------|---------------------|
|
||||
| 1分钟以内 | **1000字** |
|
||||
| 1分钟以上 | **100字** |
|
||||
|
||||
> 注意:全屏浏览模式下,文案**最多只能显示2行**(约20字),超出自动折叠
|
||||
|
||||
### 最佳实践
|
||||
|
||||
1. **显示策略**:虽然上限1000字,但前20字最关键,用户在信息流中只能看到前2行
|
||||
2. **黄金法则**:文案越简短越好,建议控制在**20字以内**
|
||||
3. **可省略情况**:如果视频中已有链接需要展示,可以直接省略文案
|
||||
4. **长文案处理**:将完整文案放在**评论区**,置顶引导点赞
|
||||
|
||||
### 文案类型推荐
|
||||
|
||||
- **简单叙事型**:描述视频背景,帮助用户理解
|
||||
- **悬念型**:设置悬念引导用户看完(如"结尾有福利")
|
||||
- **互动型**:用疑问句邀请评论("你们还想知道什么?")
|
||||
- **情绪型**:调动用户情感共鸣,使用"感动""暖心"等词
|
||||
|
||||
### 注意事项
|
||||
|
||||
- 避免频繁@多个无关账号,会被限流
|
||||
- 不建议使用视频标题直接作为文案(浪费资源)
|
||||
- 可添加话题标签(#)增加曝光
|
||||
|
||||
---
|
||||
|
||||
## 二、抖音
|
||||
|
||||
### 字数限制
|
||||
|
||||
| 元素 | 上限 |
|
||||
|-----|------|
|
||||
| 标题 | **30字** |
|
||||
| 描述(文案) | **150字符**(含标点空格),超过80字会被折叠 |
|
||||
|
||||
> 实测数据:优质内容文案控制在**80-120字**区间效果最佳
|
||||
|
||||
### 最佳实践
|
||||
|
||||
1. **黄金3秒法则**:前10-20字决定用户是否点击
|
||||
2. **结构公式**:悬念词+数字+行动指令
|
||||
- 示例:「紧急通知!3月1日前做对这3步(附教程)」
|
||||
|
||||
3. **关键词布局**:每20字嵌入1个高热关键词
|
||||
4. **情绪引擎设计**:
|
||||
- 痛点刺激:「你是不是常遇到...」
|
||||
- 解决方案:「今天教你3招破解」
|
||||
- 行动指引:「现在点击收藏还来得及」
|
||||
|
||||
### 标签与话题
|
||||
|
||||
- 使用话题标签(#)增加曝光
|
||||
- 主标签+长尾标签组合,如:#美食教程 #厨房小白必学
|
||||
|
||||
### 违禁词与雷区
|
||||
|
||||
**禁止使用**:
|
||||
- 极限词:「最」「第一」「绝对」「全世界」
|
||||
- 夸张词:「震惊」「吓死了」「胆小慎入」
|
||||
- 误导性表达:用演员真名代替剧中角色
|
||||
|
||||
---
|
||||
|
||||
## 三、小红书
|
||||
|
||||
### 字数限制
|
||||
|
||||
| 类型 | 最低要求 | 备注 |
|
||||
|-----|---------|------|
|
||||
| 短笔记 | **100字以上** | 低于100字判定为搬运 |
|
||||
| 长笔记 | **600字以上** | 平台鼓励深度内容 |
|
||||
| 标题 | **20字以内** | 超过被截断 |
|
||||
|
||||
### 标题最佳实践
|
||||
|
||||
**7种高转化标题类型**:
|
||||
|
||||
1. **画饼型**:「学会这招穿搭,气质提升一个档次」
|
||||
2. **不看会亏型**:「90%的人都不知道的省钱技巧」
|
||||
3. **数字型**:「我的5个私藏购物App」
|
||||
4. **对比反差型**:「从土气路人甲到时尚弄潮儿」
|
||||
5. **身份认同型**:「新手妈妈必看」「学生党必入」
|
||||
6. **疑问型**:「毛孔粗大怎么办?」
|
||||
7. **热点借势型**:「跟着《繁花》学穿搭」
|
||||
|
||||
**万能公式**:用户收益 + 关键词 + 解决方案
|
||||
- 示例:「小个子穿搭|这样搭配显高10cm」
|
||||
|
||||
### 正文结构(三段式)
|
||||
|
||||
1. **痛点切入**(前3行):一句话抓住注意力
|
||||
2. **干货输出**:用1.2.3.点式分点呈现
|
||||
3. **互动引导**:结尾设置互动钩子
|
||||
|
||||
### 标签策略
|
||||
|
||||
- 数量:**5-10个**标签
|
||||
- 结构:1个核心词 + 3个长尾词 + 2个场景词
|
||||
- 关键词需在标题、正文前100字、结尾各出现1次
|
||||
|
||||
### 2024-2025新规注意
|
||||
|
||||
- 原创至上:短笔记≥100字,长笔记≥600字
|
||||
- 真实要求:对比图必须标注"原相机+拍摄时间"
|
||||
- AI创作声明:使用AI生成内容必须标注
|
||||
- 禁用谐音字和极限词
|
||||
|
||||
---
|
||||
|
||||
## 四、哔哩哔哩(B站)
|
||||
|
||||
### 字数限制
|
||||
|
||||
| 元素 | 上限/建议 |
|
||||
|-----|----------|
|
||||
| 标题 | **60字**以内,建议20-30字 |
|
||||
| 简介 | 无硬性限制,建议**100字**以内 |
|
||||
| 标签 | **5-10个** |
|
||||
|
||||
### 视频描述(简介)最佳实践
|
||||
|
||||
1. **前100字嵌入关键词**:影响搜索排名
|
||||
2. **包含行动引导**:如"点赞收藏,解锁隐藏技巧"
|
||||
3. **SEO优化**:自然融入核心关键词,避免堆砌
|
||||
|
||||
### 标题结构公式
|
||||
|
||||
```
|
||||
[痛点/疑问] + [解决方案/亮点]
|
||||
```
|
||||
|
||||
示例:
|
||||
- 「为什么你的笔记没人看?90%人不知道的3个坑」
|
||||
- 「30天瘦15斤|懒人减肥法亲测有效」
|
||||
|
||||
### 标签策略
|
||||
|
||||
**推荐结构**:1个核心词 + 3个长尾词 + 2个场景词
|
||||
|
||||
示例(数码测评):
|
||||
- 核心词:iPhone15
|
||||
- 长尾词:iPhone15评测、iPhone15续航、苹果新机体验
|
||||
- 场景词:学生党推荐、数码测评
|
||||
|
||||
### B站独特玩法
|
||||
|
||||
1. **弹幕互动引导**:在视频关键节点设置弹幕触发词
|
||||
- 如:"整齐打1""弹幕护体"
|
||||
2. **评论区话题**:结尾设置开放式问题引导讨论
|
||||
3. **一键三连引导**:在视频中自然引导投币收藏
|
||||
|
||||
### 发布时间
|
||||
|
||||
- 工作日晚6-10点
|
||||
- 周末全天
|
||||
- 节假日前夕
|
||||
|
||||
---
|
||||
|
||||
## 五、四平台对比总结
|
||||
|
||||
| 维度 | 微信视频号 | 抖音 | 小红书 | B站 |
|
||||
|-----|-----------|------|-------|-----|
|
||||
| **标题/描述上限** | 1000字(实际显示2行) | 30字/150字符 | 20字/无明确 | 60字/100字 |
|
||||
| **最佳长度** | 20字以内 | 80-120字 | 100-600字 | 20-30字 |
|
||||
| **折叠临界点** | 约20字 | 约80字 | 约3行 | 视情况 |
|
||||
| **核心标签** | #话题 | #话题 | #话题 | 5-10个标签 |
|
||||
| **@功能** | 支持 | 支持 | 支持 | 支持 |
|
||||
| **推荐算法** | 社交推荐+算法 | 算法为主 | 搜索+推荐 | 播放分钟数 |
|
||||
|
||||
---
|
||||
|
||||
## 六、通用最佳实践
|
||||
|
||||
1. **前10字定生死**:无论哪个平台,前10-20字必须包含核心信息和吸引力
|
||||
2. **关键词前置**:核心关键词放在标题/描述前半部分
|
||||
3. **数字+情绪词**:使用数字具体化,用情绪词引发共鸣
|
||||
4. **互动引导**:设置问题或行动指令提升互动率
|
||||
5. **避免违禁词**:禁用极限词、夸张词、误导性表达
|
||||
6. **平台调性匹配**:
|
||||
- 抖音:娱乐化、情绪化
|
||||
- 小红书:真实体验、干货感
|
||||
- 视频号:简短正式
|
||||
- B站:知识感、互动感
|
||||
|
||||
---
|
||||
|
||||
> **数据来源**:微信开放社区官方回复、抖音创作服务中心、小红书官方运营指南、B站创作者中心,部分为2024-2025年行业实践总结。平台规则可能随时更新,建议以各平台最新官方文档为准。
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Example script - delete if not needed."""
|
||||
|
||||
print("Hello from skill!")
|
||||
@@ -0,0 +1,199 @@
|
||||
"""
|
||||
视频转录与简介生成脚本
|
||||
1. 使用 faster-whisper 转录视频
|
||||
2. 读取转录字幕,自动生成4平台简介
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
# 环境路径
|
||||
WHISPER_MODEL_PATH = "large-v3" # 使用在线模型
|
||||
|
||||
|
||||
def extract_audio(video_path):
|
||||
"""从视频提取音频"""
|
||||
audio_path = video_path.with_suffix(".wav")
|
||||
|
||||
cmd = [
|
||||
"ffmpeg",
|
||||
"-y",
|
||||
"-i",
|
||||
str(video_path),
|
||||
"-vn",
|
||||
"-acodec",
|
||||
"pcm_s16le",
|
||||
"-ar",
|
||||
"16000",
|
||||
"-ac",
|
||||
"1",
|
||||
str(audio_path),
|
||||
]
|
||||
subprocess.run(cmd, capture_output=True)
|
||||
return audio_path
|
||||
|
||||
|
||||
def format_timestamp(seconds):
|
||||
"""将秒数转换为SRT时间戳格式"""
|
||||
hours = int(seconds // 3600)
|
||||
minutes = int((seconds % 3600) // 60)
|
||||
secs = int(seconds % 60)
|
||||
millis = int((seconds % 1) * 1000)
|
||||
return f"{hours:02d}:{minutes:02d}:{secs:02d},{millis:03d}"
|
||||
|
||||
|
||||
def read_srt(srt_path):
|
||||
"""读取SRT文件,返回纯文本列表"""
|
||||
content = srt_path.read_text(encoding="utf-8")
|
||||
blocks = content.strip().split("\n\n")
|
||||
|
||||
lines = []
|
||||
for block in blocks:
|
||||
parts = block.strip().split("\n")
|
||||
if len(parts) >= 3:
|
||||
lines.append(parts[2].strip())
|
||||
return lines
|
||||
|
||||
|
||||
def generate_desc_from_subtitle(subtitle_lines, video_title):
|
||||
"""根据字幕生成4平台简介"""
|
||||
|
||||
# 提取核心内容
|
||||
main_content = subtitle_lines[:10] if len(subtitle_lines) > 10 else subtitle_lines
|
||||
|
||||
# ===== 视频号(短标题≤16字 + 描述~20字)=====
|
||||
# 短标题:提取核心关键词,不超过16字符
|
||||
if len(video_title) <= 16:
|
||||
short_title = video_title
|
||||
else:
|
||||
# 尝试提取前几个关键字
|
||||
short_title = video_title[:14] + ".." if len(video_title) > 14 else video_title
|
||||
|
||||
video_desc = f"{video_title},记住这几点!"
|
||||
if len(video_desc) > 25:
|
||||
video_desc = video_title
|
||||
|
||||
# ===== 抖音(80-120字)=====
|
||||
douyin = f"{video_title},今天一次讲清楚!\n\n"
|
||||
for i, line in enumerate(main_content[:5], 1):
|
||||
douyin += f"{i}️⃣ {line}\n"
|
||||
douyin += "\n记住这几点,弹琴更轻松~"
|
||||
if len(douyin) > 150:
|
||||
douyin = f"{video_title},3个关键点教会你!\n\n"
|
||||
for i, line in enumerate(main_content[:3], 1):
|
||||
douyin += f"{i}️⃣ {line}\n"
|
||||
douyin += "\n快学起来!"
|
||||
|
||||
# ===== 小红书(100-600字)=====
|
||||
xhs_title = f"【{video_title}】初学者必看"
|
||||
xhs = xhs_title + "\n\n"
|
||||
for i, line in enumerate(main_content, 1):
|
||||
xhs += f"▫️{line}\n"
|
||||
xhs += "\n新手学琴一定要记住这几点!"
|
||||
|
||||
# ===== B站(~100字)=====
|
||||
bz = f"【钢琴教学】{video_title}\n\n"
|
||||
bz += "【核心内容】\n"
|
||||
for i, line in enumerate(main_content[:3], 1):
|
||||
bz += f"{i}. {line}\n"
|
||||
bz += "\n适合零基础初学者学习参考~\n\n觉得有帮助请一键三连!"
|
||||
|
||||
# 标签
|
||||
tags = "#钢琴教学 #成人学琴 #零基础学钢琴"
|
||||
tags_xhs = "#钢琴教学 #成人学琴 #零基础学钢琴 #钢琴入门 #学琴日记"
|
||||
|
||||
# 组装输出
|
||||
output = f"""【标题】{video_title}
|
||||
|
||||
=== 视频号 ===
|
||||
【短标题】{short_title}
|
||||
|
||||
{video_desc}
|
||||
{tags}
|
||||
|
||||
=== 抖音 ===
|
||||
{douyin}
|
||||
{tags}
|
||||
|
||||
=== 小红书 ===
|
||||
{xhs}
|
||||
{tags_xhs}
|
||||
|
||||
=== B站 ===
|
||||
{bz}
|
||||
{tags}
|
||||
"""
|
||||
return output
|
||||
|
||||
|
||||
def transcribe_and_generate(video_dir):
|
||||
"""转录并生成简介"""
|
||||
video_dir = Path(video_dir)
|
||||
|
||||
# 查找视频文件
|
||||
video_files = list(video_dir.glob("*.mp4"))
|
||||
if not video_files:
|
||||
print(f"未找到视频文件: {video_dir}")
|
||||
return
|
||||
|
||||
video_path = video_files[0]
|
||||
video_title = video_path.stem
|
||||
print(f"处理视频: {video_title}")
|
||||
|
||||
# 1. 转录
|
||||
print("\n1. 转录视频...")
|
||||
audio_path = extract_audio(video_path)
|
||||
|
||||
import torch
|
||||
from faster_whisper import WhisperModel
|
||||
|
||||
print(" 加载模型...")
|
||||
model = WhisperModel(WHISPER_MODEL_PATH, device="cuda", compute_type="float16")
|
||||
|
||||
print(" 转录中...")
|
||||
segments, info = model.transcribe(str(audio_path), language="zh", beam_size=5)
|
||||
all_segments = list(segments)
|
||||
|
||||
# 保存SRT
|
||||
srt_content = []
|
||||
for i, segment in enumerate(all_segments, 1):
|
||||
start = format_timestamp(segment.start)
|
||||
end = format_timestamp(segment.end)
|
||||
text = segment.text.strip()
|
||||
if text:
|
||||
srt_content.append(f"{i}\n{start} --> {end}\n{text}\n")
|
||||
|
||||
srt_path = video_path.with_name(video_title + "_transcribed.srt")
|
||||
srt_path.write_text("".join(srt_content), encoding="utf-8")
|
||||
print(f" SRT保存到: {srt_path.name}")
|
||||
|
||||
# 清理
|
||||
del model
|
||||
torch.cuda.empty_cache()
|
||||
audio_path.unlink()
|
||||
|
||||
# 2. 生成简介
|
||||
print("\n2. 生成简介...")
|
||||
subtitle_lines = read_srt(srt_path)
|
||||
desc_content = generate_desc_from_subtitle(subtitle_lines, video_title)
|
||||
|
||||
desc_path = video_path.with_name(video_title + "_简介.txt")
|
||||
desc_path.write_text(desc_content, encoding="utf-8")
|
||||
print(f" 简介保存到: {desc_path.name}")
|
||||
|
||||
print(f"\n完成!")
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("用法: python transcribe_and_merge.py <视频文件夹路径>")
|
||||
sys.exit(1)
|
||||
|
||||
video_dir = sys.argv[1]
|
||||
transcribe_and_generate(video_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user