blender-motion-state-inspection
AFaffaan-m/ECC299k5,106 new stars in the last 7 days
视频下载工具:下载视频和外挂字幕文件、仅下载音频、批量下载播放列表、为本地视频烧录中文字幕。支持字幕翻译功能。当用户说'下载视频''下载这个视频''下载音频''下载播放列表''yt-dlp''烧录''烧字幕''重新烧录''烧录字幕'时使用。
config.json,取 output_dir 作为 <输出根>(支持 ~ 展开)。<输出根>/... 在执行前必须替换为真实绝对路径;禁止把 <输出根> 原样带到命令里执行(否则会写到当前目录,表现为“乱保存”)。config.json 缺失、output_dir 为空/相对路径/不可写:立即停止并提示用户在网页面板填写,或用脚本参数 --outdir <绝对路径> 覆盖。<输出根>/tmp/ 与 <输出根>/data/。例外:本地视频加字幕流程的最终输出会按下文规则询问保存位置;用户回答“默认/随便”时允许保存到原视频目录。建议的“输出根解析”固定前置步骤(避免手打长路径导致误写目录):
# 在本技能目录执行
OUTPUT_ROOT="$(python3 - <<'PY'
import json, os
from pathlib import Path
cfg = json.load(open("config.json", "r", encoding="utf-8"))
out = Path(os.path.expanduser(str(cfg.get("output_dir", ""))).strip())
if not out.is_absolute():
raise SystemExit("config.json: output_dir 必须是绝对路径或以 ~ 开头")
print(str(out))
PY
)"
mkdir -p "$OUTPUT_ROOT/tmp" "$OUTPUT_ROOT/data"
echo "OUTPUT_ROOT=$OUTPUT_ROOT"
后续所有命令都必须使用 $OUTPUT_ROOT/...,不要在命令里手写/粘贴完整长路径。
代理设置(可选):
--proxy http://127.0.0.1:7890路径说明:
<输出根>/tmp/(下文用 <输出根> 指定的根路径)config.json 设置 output_dir=<绝对路径>,或命令行 --outdir <绝对路径>(命令行优先)。output_dir 为空/缺失/相对路径时,脚本会强制提示用户输入绝对路径并写回 config.json,不允许默认回落技能目录。转写引擎(默认走脚本 scripts/transcribe_srt.py,自动下模型、零配置):
brew install whisper-cpp 并把模型下到 ~/.cache/whisper-cpp/:
~/.cache/whisper-cpp/ggml-large-v3-turbo.bin(默认模型)~/.cache/whisper-cpp/ggml-medium.bin(用户没有要求不允许使用此模型)转写模式选择逻辑:
ggml-large-v3-turbo.bin,95% 精度ggml-medium.bin,90% 精度,触发条件为用户指令中包含"快速"、"快"或"快速模式"关键词默认:保存到 <输出根>/data/(临时 <输出根>/tmp/),不再询问。
用户/工作流指定路径:优先使用指定路径。
本地视频加字幕:默认询问保存位置;“随便/默认”→视频目录,“同名”→覆盖需确认。
-o 示例都包含 <输出根>/...,不要使用裸 data/… 相对路径,否则会写到当前工作目录的 data/。config.json 的 output_dir(需用户确认,不自动填默认)。若已配置有效值则不再提示,如需重新指定请删除/清空 config.json 的 output_dir 后运行。使用场景:下载视频文件和外挂中文字幕,非中文字幕自动翻译成中文。不烧录字幕。
处理流程:
yt-dlp -f "bestvideo[vcodec^=avc1][ext=mp4]+bestaudio[ext=m4a]/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
--restrict-filenames \
-o "<输出根>/data/%(title).40s.%(ext)s" \
"${VIDEO_URL}"
vcodec^=avc1 确保下载 H.264 格式,兼容所有主流平台上传。<输出根>/data/<截断标题>.mp4HTTP Error 403 / SABR / PO Token 等问题(近一年 YouTube 风控更严格),建议使用本技能脚本自动重试并从浏览器读取 cookies:python3 scripts/youtube_download.py "${VIDEO_URL}"
--cookies-from-browser chrome 重试。python3 scripts/youtube_download.py --browser firefox "${VIDEO_URL}"yt-dlp --skip-download --write-subs --write-auto-subs \
--sub-lang "zh-Hans,zh-CN,en,ja" \
-o "<输出根>/tmp/%(id)s.%(ext)s" \
"${VIDEO_URL}"
<输出根>/tmp/<视频ID>.<语言代码>.vtt注意事项:
yt-dlp -x --audio-format mp3 --embed-thumbnail --add-metadata \
--restrict-filenames \
-o "<输出根>/data/%(title).40s.%(ext)s" \
"${VIDEO_URL}"
<输出根>/data/<截断标题>.mp3<输出根>/tmp/<视频ID>.zh-Hans.vtt 或 .zh-CN.vtt → 重命名为最终文件名并放入 <输出根>/data/(单视频文件名前缀 <截断标题>,播放列表前缀 <视频标题>-<序号>)。<输出根>/data/<目标文件名>.zh-Hans.vtt,删除原字幕。<截断标题>,播放列表用 <视频标题>-<序号> 对应字幕同名。使用场景:YouTube/Bilibili 等平台的播放列表、合集、分P。
触发关键词:URL 包含播放列表特征(如 list=、BV 开头的合集等)
交互逻辑:
--no-playlist)处理流程:
<输出根>/data/(文件名含序号):yt-dlp -f "bestvideo[vcodec^=avc1][ext=mp4]+bestaudio[ext=m4a]/bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" \
--restrict-filenames \
--playlist-items 1:5 \
-o "<输出根>/data/%(title).40s-%(playlist_index)s.%(ext)s" \
"${PLAYLIST_URL}"
火星移民计划-1.mp4。%(playlist_index)s 直接写入序号,避免重命名。<视频标题>-<序号>。--embed-subs,不烧录字幕。python3 scripts/douyin_download.py <URL> --audio|--video|--list [--resolution 1080p] [--outdir <绝对路径>]config.json 的 output_dir(或 --outdir 覆盖);临时文件写入 <输出根>/tmp/,最终文件写入 <输出根>/data/。/video/<ID>,使用可见浏览器抓取 aweme detail,成功后自动关闭。未抓到/提示未登录时,运行 python3 scripts/douyin_login.py 再重试(状态保存在 data/browser_state/douyin_profile/)。抖音初始化.md,按文档检查登录状态(用登录脚本刷新)、代理/网络、依赖是否缺失,然后重试。使用场景:用户已下载视频,需要添加中文字幕并烧录到视频画面。
触发关键词:"添加字幕"、"补救"、"加上字幕" + 本地视频路径
处理流程:
步骤1:检查是否已有字幕文件
检查视频所在目录是否存在字幕文件(按优先级):
<视频标题>.vtt<视频标题>.zh-Hans.vtt<视频标题>.srt步骤2:根据检查结果选择分支
├─ 步骤2A:如果已有字幕文件 │ (跳转到步骤3烧录) │ └─ 步骤2B:如果没有字幕文件 (使用 Whisper 转写后跳转到步骤3烧录)
步骤2A(已有字幕):中文字幕直接用;外语字幕翻译为 <输出根>/tmp/subtitle_zh.srt|.vtt 后使用。
步骤2B(无字幕):
ffmpeg -y -i "/path/to/video.mp4" -vn -acodec pcm_s16le -ar 16000 -ac 1 <输出根>/tmp/audio.wavpython3 scripts/transcribe_srt.py "<输出根>/tmp/audio.wav" --output "<输出根>/tmp/audio.srt" --language <语言>
xiaohu-subtitle-polish 技能的润色规则翻译为 <输出根>/tmp/audio_zh.srt,中文则直接使用。
步骤2C:检测视频是否已有硬字幕(烧录前必做)
烧录新字幕前,必须检查视频画面中是否已有硬编码(烧录过的)字幕:
ffmpeg -y -i video.mp4 -ss 00:00:10 -vframes 1 -update 1 /tmp/check_frame.jpg
步骤3A:烧录字幕到视频(无已有硬字幕)
使用实际验证成功的烧录命令:
cd "$(dirname "/path/to/video.mp4")"
cp "<视频标题>.mp4" temp_video.mp4
cp "<选定字幕文件>" temp_subs.srt
ffmpeg -y -i temp_video.mp4 \
-vf "subtitles=temp_subs.srt:force_style='FontName=PingFang SC,Bold=1,FontSize=24,PrimaryColour=&H00FFFFFF,OutlineColour=&H40000000,Outline=1,Shadow=0,MarginV=30'" \
-c:a copy \
"<输出文件名>.mp4"
步骤3B:避让烧录(视频已有硬字幕时)
当视频画面底部已有烧录过的字幕(如英文原字幕),新的中文字幕需要放在已有字幕上方,互不遮挡。
关键:ASS 的 MarginV 不等于像素值,不能用像素检测值直接填。必须截帧校准。
流程:
| 视频分辨率 | 已有字幕单行 | 已有字幕可能双行 |
|---|---|---|
| 1080p | MarginV=38 | MarginV=50 |
| 720p | MarginV=28 | MarginV=36 |
| 4K | MarginV=55 | MarginV=70 |
经验值来源:2026-03-10 Copilot Cowork 视频(1080p,英文字幕单行+双行混合),MarginV=50 验证通过。
ffmpeg -y -i output.mp4 -ss <双行字幕时间点> -vframes 1 -update 1 /tmp/verify.jpg
用 Read 查看截帧:
字号建议:已有硬字幕时,新字幕用 FontSize=22(比默认的 24 小一号),视觉上更协调
避让烧录命令模板:
cd "$(dirname "/path/to/video.mp4")"
cp "<视频标题>.mp4" temp_video.mp4
cp "<选定字幕文件>" temp_subs.srt
ffmpeg -y -i temp_video.mp4 \
-vf "subtitles=temp_subs.srt:force_style='FontName=PingFang SC,Bold=1,FontSize=22,PrimaryColour=&H00FFFFFF,OutlineColour=&H40000000,Outline=1,Shadow=0,MarginV=50'" \
-c:a copy \
"<输出文件名>.mp4"
说明:
-c:a copy 不重编码。步骤4:清理临时文件
# 清理 <输出根>/tmp/ 和当前目录临时文件
rm -f "<输出根>/tmp/audio.mp3" "<输出根>/tmp/audio"*.srt "<输出根>/tmp/subtitle_zh".* temp_video.mp4 temp_subs.srt
输出说明:
video_with_subs.mp4(字幕已烧录到画面)所需依赖:
yt-dlp、ffmpeg;whisper-cpp(可选备份转写引擎,不装也能用)mlx-whisper(Apple 芯片首选)或 faster-whisper(通用首选)ggml-large-v3-turbo.bin、ggml-medium.bin 下到 ~/.cache/whisper-cpp/首次使用或依赖缺失时:
AI 应自动检测依赖,如发现缺失,读取 初始化.md 文档并按指引自动安装。
安装完成后返回主流程继续执行用户请求,后续运行无需再次读取初始化文档。
临时文件位置:<输出根>/tmp/
临时文件类型:
清理策略:
tmp/ 中的原始外文字幕或音频;烧录后清理 temp_video/temp_subs。<输出根>/tmp/;最终输出文件(.mp4/.mp3/.vtt)在 <输出根>/data/,不受影响。<输出根>/tmp/。初始化.md 安装依赖后重试。AFaffaan-m/ECC299k5,106 new stars in the last 7 days
ANanthropics/skills189k2,932 new stars in the last 7 days
Generate flow fields and particle systems with p5.js, using seeded randomness for original algorithmic art.
ANanthropics/skills189k2,932 new stars in the last 7 days
SHShubhamsaboo/awesome-llm-apps144k526 new stars in the last 7 days
HAharry0703/MoneyPrinterTurbo141k3,860 new stars in the last 7 days
GAgarrytan/gstack141k2,189 new stars in the last 7 days