跳到正文
返回

氛围底片手写叠字(HealingOverlay)制作与排版布局规范

基于 Pillow + ffmpeg 的竖屏短视频模板规范。

  • 中文全称:氛围底片手写叠字
  • 中文简称:治愈叠字
  • 英文名:HealingOverlay

「氛围底片手写叠字」指全画幅氛围底片上,硬笔书法逐字写出问句并署名的竖屏短视频。

代码与资源:字体、render_overlay.py 与目录约定打包在 healing-overlay-template.zip 中(文末附下载)。手册写流程与写死参数;实现以工程包为准。


一、视频规格

项目规范
分辨率1080 × 1920(9:16 竖屏,写死)
帧率推荐 30 fps(可按底片实际帧率微调,成片统一一种帧率)
时长跟随底片(叠字写完后至少再留约 0.5s 静置;不足则循环或截取底片)
编码推荐 H.264 + AAC,色彩空间 bt709 / TV range;CRF 可按体积微调(成片母带偏高质量,分发可再压)
格式.mp4
色彩处理保留底片原色,不做滤镜、不做统一调色

画幅写死;帧率与编码写成推荐,允许按素材与平台体积要求微调,但同一批次成片参数应一致。


二、画面结构

2.1 核心原则

┌─────────────────────────────┐  1080
│  ↑ 上安全区(平台 UI)        │
│                             │
│  哪一种天气,                │  ← 问句行 1,左对齐 x=150
│  会让你突然想对自己好一点?   │  ← 问句行 2,左对齐 x=150
│           @高老师的分享局    │  ← 署名,右对齐 右缘 x=930
│                             │
│  (文字块垂直中心 ≈ 960)     │
│                             │
│  ↓ 下安全区(文案条 / 底栏)  │
└─────────────────────────────┘  1920

2.2 安全区(写死)

对齐抖音 / 视频号常见 UI 避让,语义文字不得进入下列禁区:

边常量px说明
左SAFE_L150与问句左边距一致
右SAFE_R150内容右缘 ≤ 1080 - 150 = 930
上SAFE_T220状态栏、账号信息行
下SAFE_B360文案条、音乐栏、底栏控件

内容容器(文字与可选轻量底板):

SAFE_BOX = (150, 220, 930, 1560)   # L, T, R, B
SAFE_W   = 780                     # 930 - 150
SAFE_H   = 1340                    # 1560 - 220

2.3 布局常量(写死)

项目值
画布W=1080, H=1920
问句左边距x = 150(行首对齐)
署名右缘x = 930(右对齐)
文字块垂直中心v_mid ≈ 960(H // 2)
内容最大宽780(W - 2 × 150)
问句行距行盒高度之外再加约 24px 行间空隙(按字体 metrics 算行高)

两行问句均从 x=150 起笔;署名单独一行,按字宽计算后使最后一个字形右缘落在 930。


三、字体与字色

3.1 字体(写死)

项目规范
字体霞鹜文楷(LXGW WenKai)Regular
文件工程内 fonts/LXGWWenKai-Regular.ttf(或等价路径,须可被 Pillow ImageFont.truetype 加载)
禁止换成其它楷体 / 硬笔字体冒充;本规范锁定这一款

3.2 字号(写死)

元素字号对齐
问句(两行)58px左对齐,x=150
署名 @高老师的分享局36px右对齐,右缘 x=930

问句在 58px、内容宽 780 下须整行可排下;若换文案后超宽,优先改分行或缩短文案,不要擅自改字号与边距。

3.3 字色(推荐,可微调)

用途推荐值说明
字面填充#FFF8F0 / rgba(255,248,240,255)浅暖白,适合多数氛围底
轻描边rgba(30,24,18,90) 约 1px 八邻域提高暗底可读性
投影rgba(20,16,12,160),模糊约 2.5px,偏移约 (2,3)与底片分离

底片偏亮时,可将填充略降亮或略增描边不透明度;不要改成高饱和彩色字。默认以浅色字 + 轻阴影为准。

3.4 署名(写死)

画内署名固定为:

@高老师的分享局

字号 36px,霞鹜文楷 Regular,右对齐至 x=930,与问句同一文字块、同一垂直居中逻辑。


四、时间轴与逐字动画

4.1 硬性节奏

阶段规范
开场空镜写死 2.0s:t ∈ [0, 2.0) 画面只有底片,无字
问句写出t = 2.0 起,按公式逐字左→右 wipe
问句与署间隔0.35s 静置(问句末字写完 → 署名首字开始)
署名写出同样公式逐字 wipe
写完后保持终态叠字至片尾

成片实测对照(示例问句 19 字 + 署名 8 字):

节点时刻
问句首字开始2.000s
问句写完4.880s
署名开始5.230s
署名写完6.460s

4.2 单字时长公式(可算)

常量:

DELAY_START   = 2.0    # 开场空镜,写死
CHAR_STAGGER  = 0.15   # 相邻字开始时刻间隔(秒)
CHAR_WIPE     = 0.18   # 单字左→右 wipe 时长(秒)
PAUSE_BEFORE_AT = 0.35 # 问句完成到署名开始

设问句字符序列为 Q[0..n-1](含标点,按 Unicode 码点计字),署名为 A[0..m-1]:

Q_start[i] = DELAY_START + i * CHAR_STAGGER
Q_done[i]  = Q_start[i] + CHAR_WIPE
Q_done     = Q_done[n-1]          # = DELAY_START + (n-1)*CHAR_STAGGER + CHAR_WIPE

A_start[j] = Q_done + PAUSE_BEFORE_AT + j * CHAR_STAGGER
A_done[j]  = A_start[j] + CHAR_WIPE
A_done     = A_done[m-1]

校验(本规范示例文案):

n = len("哪一种天气,会让你突然想对自己好一点?")  # 19
m = len("@高老师的分享局")                      # 8
Q_done = 2.0 + 18*0.15 + 0.18 = 4.88
A_start = 4.88 + 0.35 = 5.23
A_done  = 5.23 + 7*0.15 + 0.18 = 6.46

换文案时只改 Q / A 字符串,用公式重算;不要改 DELAY_START。

4.3 Wipe 动画(左→右)

伪代码:

def ease_out_cubic(t: float) -> float:
    t = max(0.0, min(1.0, t))
    return 1.0 - (1.0 - t) ** 3

def char_progress(t: float, start: float, wipe: float = CHAR_WIPE) -> float:
    return (t - start) / wipe  # 再 clamp 到 [0,1] 后送入 wipe

五、氛围底片

项目规范
来源任意竖屏氛围素材(实拍 / 库存均可)
画幅建议已是 9:16;若不是,先 crop/scale 成 1080×1920 再叠字
色彩保留原色,禁止统一滤镜、禁止强对比拉伸
音轨可保留底片原声;也可无音轨(本规范不强制 BGM)
内容不遮挡中部安全区关键信息;文字区尽量避开人脸五官与大面积高亮招牌字

示例成片说明(占位,不挂真实链接):

示例成片:雨天氛围底片 + 问句「哪一种天气,会让你突然想对自己好一点?」+ 署名 @高老师的分享局,按本规范叠字导出。工程包见文末下载 healing-overlay-template.zip(含字体与 render_overlay.py);成片样例可选,本站暂不挂 mp4。


六、制作流程(Pillow + ffmpeg)

不单开 Agent 清单;按下列步骤执行即可复现。

6.1 目录约定

工程包 healing-overlay-template.zip 解压后即为下列结构(顶层文件夹名 healing-overlay-template/,与下表路径一致;亦可将目录改名为 healing-overlay/)。

healing-overlay/                 # 项目英文名 HealingOverlay,中文名氛围底片手写叠字
├── fonts/
│   └── LXGWWenKai-Regular.ttf   # 写死字体
├── source/
│   └── base.mp4                 # 氛围底片(已是或将转为 1080×1920)
├── frames/                      # 透明叠字序列 frame_0000.png …
├── render_overlay.py            # Pillow:排版 + wipe 出帧
├── out/
│   ├── final.mp4                # 成片
│   ├── first_frame.png          # 封面选中帧(9:16,可选)
│   └── cover_3x4.png            # 3:4 封面(可选)
└── README.md                    # 可选:指向本规范

6.2 Step 1 · 准备底片

# 统一到 1080×1920;帧率推荐 30(可按素材微调)
ffmpeg -y -i source/raw.mp4 \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920,setsar=1,fps=30,format=yuv420p" \
  -c:v libx264 -crf 18 -pix_fmt yuv420p \
  -colorspace bt709 -color_primaries bt709 -color_trc bt709 -color_range tv \
  -c:a aac -movflags +faststart \
  source/base.mp4

用 ffprobe 确认分辨率与色彩标签。保留原色,不要加 eq/curves 等滤镜。

6.3 Step 2 · 排版与出叠字帧(Pillow)

render_overlay.py 关键职责:

  1. 用 LXGWWenKai-Regular.ttf 以 58 / 36 量问句与署名。
  2. 问句两行左对齐 x=150;署名右对齐到 x=930;整块垂直居中使 v_mid ≈ 960。
  3. 按第四节公式算每个字的 start;对每一视频帧 t = fi / fps 合成透明 RGBA。
  4. 导出 frames/frame_%04d.png(与底片同帧率、同帧数或覆盖至 A_done 之后)。

布局自检(出片前打印):

block L=150 R=930 v_mid≈960
Q_SIZE=58 AT_SIZE=36
first_start=2.000 …

任一项偏离写死值,先改脚本再渲染。

6.4 Step 3 · 合成成片(ffmpeg)

透明 PNG 序列叠到实拍底片上(示例):

FPS=30
ffmpeg -y \
  -i source/base.mp4 \
  -framerate $FPS -i frames/frame_%04d.png \
  -filter_complex "[0:v][1:v]overlay=0:0:format=auto,format=yuv420p" \
  -c:v libx264 -crf 18 -pix_fmt yuv420p \
  -colorspace bt709 -color_primaries bt709 -color_trc bt709 -color_range tv \
  -c:a copy \
  -shortest \
  -movflags +faststart \
  out/final.mp4

6.5 Step 4 · 验收

检查项标准
分辨率1080×1920
开场前 2.0s 无字
对齐问句左缘 150;署名右缘 930;块中心 ≈960
字号问句 58;署名 36
字体确认为霞鹜文楷 Regular
安全区字形未入上 220 / 下 360 禁区
动画左→右 wipe,非淡入
色彩底片观感与源片一致(原色)
署名文案为 @高老师的分享局

七、关键实现要点(摘录)

7.1 右对齐署名

AT = "@高老师的分享局"
at_font = ImageFont.truetype(FONT_PATH, 36)
at_w = at_font.getlength(AT)
at_x = 930 - at_w   # 右缘落在 930

7.2 垂直居中文字块

V_CENTER = 1920 // 2  # 960
# total_h = 各行行高之和 + 行距
y0 = int(round(V_CENTER - total_h / 2))

7.3 单字开始时刻

DELAY_START, CHAR_STAGGER, CHAR_WIPE = 2.0, 0.15, 0.18
starts = [DELAY_START + i * CHAR_STAGGER for i in range(n)]
# 末字完成 = starts[-1] + CHAR_WIPE

完整 wipe / 描边 / 投影实现以工程内 render_overlay.py 为准;本规范约束数值与行为,不绑定某一份脚本文件名。


八、快速修改对照表

想改什么改哪里参数 / 规则
开场空多久DELAY_START保持 2.0(本规范写死)
手写快慢CHAR_STAGGER / CHAR_WIPE默认 0.15 / 0.18;改后用公式重算
问句文案字符串 Q + 分行左对齐 150;超宽先改分行,不改边距
署名字号AT_SIZE保持 36
问句字号Q_SIZE保持 58
左右边距MARGIN_LR保持 150(右缘恒为 930)
垂直位置V_CENTER保持 960
字色填充 / 描边 / 阴影推荐浅色,可按底片明暗微调
底片source/base.mp4任意竖屏氛围素材,原色
帧率ffmpeg fps=推荐 30,可微调但需与 PNG 序列一致
体积成片 CRF / 二次压制母带质量优先,分发再压
封面 / 首帧成片选帧 N(须 ≥ A_done)裁 crop=1080:1440:0:240;有声须 adelay

九、注意事项

  1. 不要做成 CaptionReel 式「上半字卡、下半影像」;本模板是全画幅底片 + 中部叠字。
  2. 不要把开场空镜改成 0;2.0s 是写死节奏,用于先看氛围再出字。
  3. 不要用淡入、缩放弹入代替左→右 wipe;手写感依赖 wipe 方向与错峰。
  4. 不要更换霞鹜文楷 Regular;字号与边距按该字体标定。
  5. 不要把署名改成其它账号;规范写死 @高老师的分享局。
  6. 换问句后必须重算时间轴,并用 timing_proof(或等价日志)核对 Q_done / A_done。
  7. 合成时保持 bt709 / yuv420p,避免把底片洗成错误色彩范围。
  8. 安全区上 220 / 下 360 为平台 UI 避让;左右 150 同时是排版边距,二者一并遵守。
  9. 本规范不覆盖发布标题与话题标签;发布文案另案处理。
  10. 封面选帧须在问句与署名全部写完之后(t ≥ A_done);3:4 裁切后问句两行与署名 @高老师的分享局 须完整可见,不得带病上线。详见第十节。
  11. 模板工程包附在本手册:healing-overlay-template.zip(字体 + render_overlay.py + 目录约定);成片样例 mp4 仍可选,不强制挂链。

十、封面与首帧

封面从成片取一帧,不另做设计。流程对齐 字卡影 · 封面与首帧 / 主片卡,并按本模板约定。

本模板常用 Pillow + ffmpeg 管线,成片路径写死为 out/final.mp4;封面命令一律对成片取帧,不要用 Remotion still。有音轨时必须 adelay;无音轨跳过 adelay,见 10.3。

10.1 取帧与 3:4 封面

IN=out/final.mp4
FPS=30
N=200   # 示例:须 ≥ ceil(A_done*FPS);示例文案约 ≥194

ffmpeg -i $IN -vf "select=eq(n\,$N)" -frames:v 1 out/first_frame.png
ffmpeg -i out/first_frame.png -vf "crop=1080:1440:0:240" out/cover_3x4.png
# 目视检查 cover_3x4.png:问句两行 + 署名完整可见

10.2 插入首帧(有音轨 · 默认)

氛围底片常保留原声。插帧后须把音频整体后延 1 帧,否则音画错位。用 adelay 按采样数延迟(采样率 ÷ FPS,例如 48 kHz / 30fps → 1600 采样),all=1 作用于所有声道;不做任何音量处理。PNG 与成片统一成 yuv420p(TV 范围),再用 setpts=N/(FPS*TB) 重排时间戳,避免插入帧与主片首帧时间戳重叠被丢帧。

IN=out/final.mp4
FPS=30
N=200   # 与 10.1 同一选帧
SR=$(ffprobe -v error -select_streams a -show_entries stream=sample_rate -of csv=p=0 $IN)
D=$((SR / FPS))                    # 1 帧对应的采样数

ffmpeg -i $IN -vf "select=eq(n\,$N)" -frames:v 1 out/first_frame.png
ffmpeg -i out/first_frame.png -vf "crop=1080:1440:0:240" out/cover_3x4.png

ffmpeg -loop 1 -framerate $FPS -i out/first_frame.png -i $IN \
  -filter_complex "\
[0:v]scale=out_range=tv,format=yuv420p,setsar=1,fps=$FPS,trim=end_frame=1,setpts=PTS-STARTPTS[f];\
[1:v]format=yuv420p,setsar=1,fps=$FPS,setpts=PTS-STARTPTS[m];\
[f][m]concat=n=2:v=1:a=0,setpts=N/($FPS*TB)[v];\
[1:a]adelay=delays=${D}S:all=1,asetpts=PTS-STARTPTS[a]" \
  -map "[v]" -map "[a]" -r $FPS \
  -c:v libx264 -crf 16 -pix_fmt yuv420p -color_range tv \
  -c:a aac -b:a 192k -ar $SR -movflags +faststart out/final_with_cover.mp4

10.3 无音轨

若底片无音轨(或成片已 -an),插帧时跳过 adelay,只做取帧、裁封面、插首帧:

IN=out/final.mp4
FPS=30
N=200

ffmpeg -i $IN -vf "select=eq(n\,$N)" -frames:v 1 out/first_frame.png
ffmpeg -i out/first_frame.png -vf "crop=1080:1440:0:240" out/cover_3x4.png

ffmpeg -loop 1 -framerate $FPS -i out/first_frame.png -i $IN \
  -filter_complex "\
[0:v]scale=out_range=tv,format=yuv420p,setsar=1,fps=$FPS,trim=end_frame=1,setpts=PTS-STARTPTS[f];\
[1:v]format=yuv420p,setsar=1,fps=$FPS,setpts=PTS-STARTPTS[m];\
[f][m]concat=n=2:v=1:a=0,setpts=N/($FPS*TB)[v]" \
  -map "[v]" -r $FPS \
  -c:v libx264 -crf 16 -pix_fmt yuv420p -color_range tv \
  -an -movflags +faststart out/final_with_cover.mp4

十一、与同系列其它短视频模板的区别

氛围底片手写叠字 HealingOverlay字卡影 CaptionReel贴文卡 PostCard杂志撕纸风 MG
结构全画幅氛围底 + 中部手写叠字上半文字卡、下半影像黑底上的柔白帖文卡多镜撕纸 MG 拼接
常见技术栈Pillow + ffmpegRemotionRemotionPillow + ffmpeg
文字呈现硬笔左→右 wipe淡入 + 轻缩放段落淡入标签 / 结论句贴图
左右边距150 / 右缘 930100卡片宽 880 居中L64 / R128
开场强制空 2.0s文字约 1s 内入场约 2s 内淡入完随旁白分镜

本文档作为 HealingOverlay 氛围底片手写叠字模板的设计与制作规范,持续迭代中。


模板工程包下载

⬇︎ healing-overlay-template.zip(约 11.1MB,14 个文件)——内含霞鹜文楷 Regular、render_overlay.py(排版+wipe)、空的 source/frames/out 目录与 example/script.txt。解压后按本手册第六节执行。


上一篇
字卡影快闪短视频(CaptionReel)制作与排版布局规范
下一篇
像素 MV 顶格迭代 Skill:从优秀案例拆配方到可复用工作流