Communitygithub.com

手机竖版视频编辑

将手机拍摄的视频编辑为竖屏 Reels、Shorts 或 TikTok 的完整工作流程,包含阿拉伯语屏幕文字。涵盖源文件检查、剪切、稳定、慢动作、色彩校正、阿拉伯语 Remotion 文字、音频剪辑和响度母带等环节。

手机竖版视频编辑 是什么?

该技能定义了一个完整的手机竖版视频编辑流程,专门用于将手机拍摄的原始素材处理为适合 Instagram Reels、YouTube Shorts 和 TikTok 的竖屏视频,并支持阿拉伯语屏幕文字。它基于一套经过实际测试的规则,从源文件检查开始,依次进行剪切、稳定(使用 vidstab)、颜色校正(通过 ffmpeg LUT 或 DaVinci Resolve 免费版,基于测量值调整)、Remotion 中的阿拉伯语文字叠加(包含自动重叠检查、安全区域和对比度校验),以及音频与最终母带处理。该技能特别强调通过精确的数值测量(如色卡、肤色、白平衡)来确保色彩准确性,并通过脚本自动执行文本布局、对比度和安全区域检查。它支持 macOS、Linux 和 Windows 上的 Claude Code 使用,也可在 Cursor 和 Codex 中工作,需要 Python、Node.js、ffmpeg 和 vidstab 滤镜。对于有 Resolve 的桌面环境,它提供了详细的 Power Window 工作流程。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/amrodwaire/phone-reel-edit/tree/HEAD

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

手机竖版视频编辑 是做什么的?

这里的大多数规则都来自一个在相应步骤上失败过的真实视频。references/research.md 中记录了原因和来源。references/resolve-ui.md 映射了 DaVinci Resolve 的控制界面,以便通过计算机操作来驱动。

部分情况尚未经过已发布的视频验证:HDR 源、30 fps 慢动作、镜头前的讲话、TikTok 和 Shorts 的安全框以及封面。这些命令仅在测试片段上运行过。references/other-cases.md 中记录了它们,并说明了每个命令的验证方式。当编辑依赖其中某项时,请告知用户。

流程:手机源文件、ffmpeg 剪切与稳定、色彩(DaVinci Resolve,或用于全帧操作的 scripts/grade.py)、Remotion 文字、ffmpeg 音频与母带。

剪切前

  1. 阅读客户的品牌规则(如有):禁用词汇、联系方式、AI 标注、以及发布前需要审批的内容。
  2. 检查每个源片段:python -I scripts/probe_source.py clip.mp4。它会报告旋转、帧率及其是否可变、SDR 或 HDR、色彩标签和音频,然后列出该片段在剪切前需要处理的事项。典型手机片段为 SDR bt709,帧率约 30 或 60 fps。HDR、可变帧率和 30 fps 源分别需要额外步骤,请参考 references/other-cases.md。背景谈话意味着原始声音保持静音。如果镜头中的人物正在对观众讲话,请查看同一文件中的“讲话”部分。
  3. 如果你使用另一个 AI 模型作为审核者,在决定前与其讨论想法,然后验证它所说的内容。references/research.md 列出了审核模型可能犯的错误类型。

节奏

  • 每条视频一个想法。文字决定时长,而不是预设的目标长度。一个测试视频因客户在 10.5 秒或 13.5 秒内无法读完,所以需要 18.6 秒。
  • 按每行出现的时间计算,每秒预留 10 个阿拉伯语字符。这故意放慢,因为观众同时还要在手机上观看画面。
  • 每个镜头尽量有两个揭示点,并且它们之间至少有 1.5 秒的间隔。同时出现的文字行算作一个揭示点。
  • 母语读者对节奏的判断比任何模型的判断都重要。
  • 最强的视觉画面和钩子文字出现在第 0 帧,没有从黑色淡入。
  • 避免突然的 3 倍速度变化。可以通过缓慢的渐变来处理糟糕的时刻。

60 fps 以 0.5 倍播放时,实际帧率为 30 fps,因此不需要插帧。30 fps 源没有多余帧,因此在放慢前请阅读 references/other-cases.md 中的慢动作部分。先稳定到 60 fps 的中间格式,然后再调整时间:

ffmpeg -ss S -t D -i raw.mp4 -vf "vidstabdetect=shakiness=6:accuracy=15:result=x.trf" -f null -
ffmpeg -ss S -t D -i raw.mp4 -vf "vidstabtransform=input=x.trf:smoothing=14:zoom=2:optzoom=0:interpol=bicubic,crop=W:H:X:Y,scale=1080:1920:flags=lanczos,fps=60" -an -c:v libx264 -preset veryfast -crf 10 -pix_fmt yuv420p im.mp4
python -I scripts/retime.py im.mp4 c1.mp4 --start 0.4 --frames 99 --keys 0:.5

从本技能的文件夹运行 scripts/ 路径。ffmpeg 需要 vidstab 滤镜。每个片段必须从零时间开始,因为非零开始时间会在 Resolve 中显示为黑帧。当使用 -ss 配合时间滤镜时,添加 setpts=PTS-STARTPTS,并用 ffprobe 检查 start_time。

如果手部进入静止镜头的最后几帧,可以通过保持前一帧来隐藏:trim=end_frame=N,setpts=PTS-STARTPTS,tpad=stop_mode=clone:stop_duration=0.6。

色彩

定义:这里的色彩指的是校正:中性的白色、自然的肤色、真实的产品颜色、镜头匹配。创意调色放在最后,且保持细微,产品颜色在调色后仍须测量准确。

根据镜头的需求选择路径:

  • 仅全帧操作(色温、曝光、对比度、饱和度):使用 scripts/grade.py。它更快、可重复,且数值保留在可重新运行的命令中。
  • 画面某部分需要单独修正(不同光线下的肤色、某个物体):使用 DaVinci Resolve 及其 Power Window。

两种路径都使用相同的测量、调整、测量循环以及以下目标值。

使用 grade.py

python -I scripts/grade.py still c1.mp4 1.5 before.png
python -I scripts/measure_grade.py before.png --patch counter:40,60,200,220 --skin 100,1450,1000,1920
python -I scripts/grade.py make c1.cube --frame before.png --neutral 40,60,200,220 --white 205 --contrast 1.06 --pivot 0.4 --lift -0.02
python -I scripts/grade.py still c1.mp4 1.5 check.png --lut c1.cube --compare
python -I scripts/grade.py apply c1.mp4 c1g.mp4 --lut c1.cube

--neutral 是一个应该呈灰色或白色的区域:台面、墙壁、纸张、白色盖子。make 会平衡其 R、G、B 通道,--white 设置最终亮度水平。选择照明均匀且未过曝的区域。在应用前,以全尺寸查看 --compare 帧,并测量已调色的一半。每个镜头一个 LUT,因为每个镜头有自己的色偏。

当增益将高光推过 250 时,添加 --knee 0.85。仅对明显噪点多、光线不足的片段使用 --denoise light,很少使用 --sharpen:手机已经进行了锐化,再增加会导致边缘和文字出现光晕。

在 Resolve 中创建的调色可以导出为 LUT:在 Color 页面右键点击片段的缩略图,选择“Generate LUT”,33 Point Cube。然后 grade.py apply --lut 可将其应用于任何片段。LUT 仅包含全帧操作,因此窗口操作不包含在内。

在 DaVinci Resolve 免费版中

将片段复制到一个 Resolve 可以访问的普通文件夹中(它无法打开某些应用数据文件夹,会显示“Path does not exist”)。将它们放在新时间线上,并打开 Parade 示波器。

按以下顺序操作,因为每个步骤都依赖于前一个:

  1. 平衡节点。 用 Gain 调整白色水平,用 Temp 调整色偏。正 Temp 使画面变暖。两个镜头中的同一条面必须匹配。
  2. 对比度节点。 调整 Contrast 和 Pivot,用 Lift 加深黑色,进行不超过 5 的小幅 Sat(饱和度)调整。
  3. 主体节点,仅在全局调整会损坏其他部分时使用。 使用柔和的 Power Window。在测试视频中,一个窗口修正了手部肤色,同时保持了产品颜色不变。
  4. 渲染、测量、调整、重复。两遍就足够了。
python -I scripts/measure_grade.py frame.png --patch counter:40,60,200,220 --skin 100,1450,1000,1920

目标值

  • 中性表面:R、G、B 差值在约 3 到 5 以内。白色约 195 到 215,呈现明亮效果。
  • 肤色色调接近 123 度。保持自然,因为矢量示波器上的线是参考,不是目标。
  • 肤色亮度:指南建议根据肤色和场景,在 40% 到 70% 之间。使用此范围来发现错误,而非作为必须达到的数字。
  • 高光部分中,约 2% 以下的像素达到 250+。
  • 饱和度:比较调色前后的 chroma 线。校正后 p95 应保持在接近原始值的位置。大幅跳跃意味着调色添加了场景中没有的颜色。
  • 产品颜色在视频销售产品时必须保持真实。
  • 同一表面的两个镜头测量结果相同。

各调整的作用:

  • Tint 对红色手掌几乎无效。按通道调整 Gamma 修复了它:提高 G,稍微降低 R 和 B。
  • Temp +300 对蓝色色偏过度调节,而 +130 是合适的。从小幅调整开始。

Remotion 中的阿拉伯语文字

assets/reelTemplate.tsx 是一个可用的模板。它将每个文本块保存为数据,并包含一个用于文本检查的 probe 合成。references/remotion-setup.md 涵盖了从零开始项目以及注册合成的方法。

规则:

  • 使用粗体的阿拉伯语字体(模板使用 Alexandria 800),白色加上一种强调色,无边框,柔和的阴影。
  • 在 1080x1920 的帧上,字号为 62 到 124 px。手机需要这么大的字号。
  • 阿拉伯语的行高(line box)设为 1.5。在 1.22 时,字母的尾笔会碰到下一行。
  • 所有字母位于 x 110-950 和 y 220-1475 范围内,以确保不被 Instagram 的右侧栏和底部栏遮挡。
  • 使用 whiteSpace: nowrap,防止行意外换行。
  • 钩子文字在第 0 帧显示。后续文字行大约间隔 1 秒,带有 6 帧的上升和淡出效果。
  • 在文字后方添加柔和的深色条带,以保证文字下方的主体可见。
  • 客户引述必须逐字保留,未经客户同意不得包含姓名或照片。
  • 描述观众正在看到的内容。不要让标签暗示这是唯一的选项。

在文字更改后,渲染 probe 帧并进行检查:

npx remotion still ReelProbe out/p0.png --frame=0
python -I scripts/check_text.py out/p0.png out/p1.png out/p2.png out/p3.png

当两行文字的油墨距离小于 14 px 或字母离开安全框时,检查将失败。一个文字块最多容纳七行。

然后检查文字与真实画面的重叠效果。渲染每个镜头的最后一帧(此时所有文字行都在屏幕上),并按相同顺序传递这些帧:

npx remotion still Reel out/r0.png --frame=119
python -I scripts/check_text.py out/p0.png out/p1.png --real out/r0.png out/r1.png

每行都会获得一个对比度数值,该数值计算自文字周围画面最亮部分。数值低于 3.0 则失败。在测试视频中,强调色的文字得分在 3.2 到 4.6 之间,白色文字得分为 5 及以上。低分意味着需要在文字后方使用更强的深色条带,或移动文字块。

默认安全框是 Instagram 的。对于也发布到 TikTok 或 Shorts 的视频,添加 --platform all。这两个平台的安全框来自第三方指南,因此请在每个应用中预览上传效果。

然后,查看每个镜头结尾处的全尺寸帧。缩略图表格会隐藏碰撞,而文字后移动的物体只有在全尺寸下才能看到。在测试视频中,一把勺子穿过了一行文字。通过一个角起点的小幅缩放将其移开,同时也裁剪了多余的手指。

渲染与音频

npx remotion render Reel out/reel.mp4 --codec=h264 --crf=15 --muted --color-space=bt709
python -I scripts/beat_offset.py music.ogg --cuts 3.3,6.5,10.3 --length 13.5 --from 0 --to 40

--color-space=bt709 很重要。没有它,Remotion 会写入全范围的 bt470bg,且主色彩未知。

从最佳偏移点剪切音乐,淡出最后 1.2 秒,使用 -c:v copy 拼接,然后进行母带处理:

sh scripts/master.sh in.mov out.mp4 -14 0.4 0.75

最后一个数字是限制器天花板。AAC 音频编码会在其之上产生过冲,冲量取决于音轨本身,因此该脚本会测量它写入的文件并打印其响度和真实峰值。如果打印出 TOO HOT(真实峰值高于 -1 dBTP),请使用 0.7 重新运行。

手机扬声器会丢失大部分 300 Hz 以下的声音,因此要检查该频段:

ffmpeg -hide_banner -nostats -i out.mp4 -vn -af "highpass=f=300:poles=2,highpass=f=300:poles=2,lowpass=f=12000,ebur128" -f null - 2>&1 | tail -12

目标是在 -14 LUFS 的母带中,该频段达到 -20 LUFS 或更响亮。一个重低音轨测量为 -23.9 LUFS,在手机上听起来很沉闷。也要绘制波形图和频谱图,因为审核模型的时间戳并不总是与它们匹配。

AI 生成的音乐或人声需要平台的 AI 标签。生成的音乐要比视频稍长,因为被剪短的音轨无法干净地延长。

完成前的检查

  • ffprobe 显示 yuv420p, tv, bt709, bt709, bt709,以及正确的时长和帧数。
  • check_text.py 打印出 PASS,并包含 --real 帧。
  • master.sh 打印出的真实峰值等于或低于 -1 dBTP。
  • 如果视频显示在个人资料网格上,则需要存在封面帧(references/other-cases.md)。
  • 亲自查看全尺寸帧,包括第一帧和最后一帧以及每个剪切点之前的帧。
  • 如果审核模型观看最终的 mp4,请向其提供已经做出的决定,以免它重新开启这些决定。
  • 说明哪些内容未被检查。AI 无法听到音频或在手机上看到文件。
  • 在替换已上传的文件后,重新上传,从公共链接验证,并更新任何指向旧文件的计划内容。

发布需要客户的批准。

相关技能