用于在保持宽高比倒置的情况下,将视频从横向转换为纵向或反之(例如 16:9 ↔ 9:16,4:3 ↔ 3:4 等)
wjs-reframing-video. 通过从源头裁剪狭带来转换视频的导向,而不是通过物理旋转. 作物窗口跟随活动扬声器(其嘴是脸)是一项面向实际任务的技能。它将相关步骤、工具调用和结果整理方式集中到统一流程中,帮助使用者更快完成目标并减少重复操作。
实际使用前应先确认任务范围、数据来源、运行环境、必要权限和关键参数,再依据技能说明逐步执行;若输入条件不完整,应先补齐信息或采用保守配置,避免因错误假设导致结果偏离需求。
执行过程中需要关注工具调用是否成功、接口或依赖是否可用、输出格式是否符合预期,并对异常提示、缺失字段和边界情况进行处理;涉及批量任务时,还应保存进度,避免中断后重复操作。
通过从源视频中裁剪一个窄条区域来改变视频朝向,而非物理旋转画面。裁剪窗口始终跟随正在说话的人(active speaker)——即嘴部正在运动的面部,而非仅依据面积最大或置信度最高的面部。配套生成的 .crop.json 辅助文件记录了完整的裁剪方案、各片段的发言人判定结果,以及所用参数。原始输入文件**永远不会被修改**。
输出画幅为源画幅的宽高互换 —— 即 16:9 → 9:16,而非“在 9:16 画框内添加黑边的 16:9”。
| 是 | 不是 |
|---|---|
| 基于 MAR(嘴部宽高比)方差的视觉主动发言人检测 | 音视频融合(音频能量 + 嘴唇运动交叉相关) |
| 通过中心距离匹配实现跨帧稳定人脸追踪 | 长间隔 / 遮挡场景下的人脸重识别 |
| 带迟滞(hysteresis)机制的发言人对齐分段,防止画面闪烁 | 逐帧切换(每出现一次微小波动即切换) |
--face-pick speaker(默认)—— 选择嘴部正在运动者 |
--face-pick largest(可选旧模式)—— 选择面积最大者 |
分段间硬切,每段内裁剪位置固定(--motion cut,默认) |
平滑平移,且在单人发言过程中持续漂移(可选 --motion smooth) |
| 音频流拷贝(比特精确) | 音频重处理 / 重编码 |
使用 MediaPipe Tasks FaceLandmarker(478 点网格),通过 ffmpeg 以 5 fps 采样 |
逐帧神经网络图像修复 / 外绘(inpainting / out-painting) |
单次 ffmpeg crop + scale 处理 |
逐帧 Python 合成器 |
当无人讲话(静音、纯音乐段落)时,自动回退至“面积最大面部”策略。
pip install mediapipe opencv-python numpy
(MediaPipe 不包含在标准 Python 发行版中;ffmpeg 和 ffprobe 必须位于系统 PATH 中。)
首次运行模型下载:MediaPipe 0.10+ 使用 Tasks API,需加载 face_landmarker.task 模型文件(约 4 MB)。首次调用时,crop.py 将自动下载至 ~/.claude/skills/wjs-reframing-video/models/ 并缓存,供后续运行复用。首次离线运行将失败。
检测距离限制:内置 landmark 检测器针对距摄像头约 2 米范围(自拍 / 播客 / 访谈距离)优化。广角活动场景中若人脸过小可能无法检出 —— 建议先抽帧验证检测效果。
源画幅 = W / H,目标画幅 = H / W(倒置)。裁剪窗口计算如下:
| 源朝向 | 裁剪窗口 |
|---|---|
| 横屏(W > H)→ 竖屏 | W_crop = H × H / W,H_crop = H(垂直窄条) |
| 竖屏(W < H)→ 横屏 | W_crop = W,H_crop = W × W / H(水平窄条) |
例如 1920×1080 → 竖屏: W_crop = 608,H_crop = 1080;最终缩放至 1080×1920(约 1.78× 上采样)。
1080×1920 → 横屏: W_crop = 1080,H_crop = 608;最终缩放至 1920×1080。
若希望输出为原生裁剪尺寸而非上采样,可通过 --output-size 1080x1920 手动指定最终尺寸。
--target portrait|landscape 手动覆盖)。--sample-fps(默认 5 fps)采样帧 —— 足够捕捉嘴部运动(语音奈奎斯特频率约 10 Hz,至少需 4–5 fps)。FaceLandmarker(478 点)检测人脸关键点。对每个检测到的人脸记录:中心坐标、尺寸代理值、MAR(嘴部宽高比 = 内唇垂直距离 / 嘴角水平距离)。face_id。--mar-var-window-sec,默认 1 秒)内计算 MAR 方差。方差最高者视为“正在说话”。若低于 --mar-var-threshold,则判定为无声 → 回退至面积最大者。--min-segment-sec(默认 1.5 秒)后才生效;更短的抖动将被抑制 —— 避免因单帧误检导致裁剪窗口来回跳变。--motion cut,默认):使每段裁剪位置恒定,并在段边界处瞬时跳变 —— 视觉效果等效于真实摄像机角度切换。(--motion smooth 切换为分段线性平移,但对访谈类内容通常不适用,因镜头会在句中漂移。)crop=W:H:x='expr':y='expr', scale=OUT_W:OUT_H。crop 滤镜原生支持逐帧计算 x 与 y;音频流拷贝。scripts/crop.py 为具体实现。输出副作用包括:
.crop.json —— 记录裁剪方案的辅助文件_cropped.mp4 —— 最终裁剪并缩放后的视频.crop.json){
"_about": "wjs-reframing-video crop plan for cam_a.MOV. Active-speaker detected via MAR variance.",
"_help": {
"source_size": "[width, height] in pixels.",
"target_size": "[width, height] of the final rendered output.",
"crop_window": "[width, height] of the moving crop in source coords.",
"chunks": "Speaker-aligned segments: {t0, t1, cx, cy, speaker_id}.",
"face_pick_mode": "speaker = MAR-variance active-speaker; largest = old behavior.",
"speaker_id": "Stable face track id. null means no face / silence fallback."
},
"schema_version": 2,
"source": "cam_a.MOV",
"source_size": [1920, 1080],
"target": "portrait",
"target_size": [1080, 1920],
"crop_window": [608, 1080],
"face_pick_mode": "speaker",
"sample_fps": 5.0,
"mar_var_window_sec": 1.0,
"mar_var_threshold": 1.5e-4,
"min_segment_sec": 1.5,
"chunks": [
{"t0": 0.0, "t1": 4.2, "cx": 808, "cy": 540, "speaker_id": 0},
{"t0": 4.2, "t1": 11.6, "cx": 1182, "cy": 540, "speaker_id": 1},
{"t0": 11.6, "t1": 14.0, "cx": 808, "cy": 540, "speaker_id": 0}
],
"face_sample_count": 1234,
"track_count": 2
}
--sample-fps 会使检测变慢,但追踪响应更灵敏。hevc_videotoolbox)。1080p 源视频常低于 1× 实时速度。face#N: Xs on screen (Y%) 汇总),必要时调整 --mar-var-threshold 后重试。--face-pick largest。ffmpeg lenscorrection 校正畸变。608×1080 → 1080×1920 需 1.78× 上采样,锐利文字可能出现可见失真。若需保持叠加图层清晰度,可输出原生裁剪尺寸(--output-size 608x1080),交由平台自行上采样。--bitrate 12M。微信视频号上限为 10 Mbps;针对该平台请指定 --bitrate 8M。相关专题
热门下载
相关下载
精品课程
共39课时 | 5.4万人学习
共101课时 | 21万人学习
共39课时 | 4.8万人学习
最新文章