跳到正文
返回

快讯风竖屏短视频(NewsFlash)制作与排版布局规范

基于 HyperFrames(单 HTML + GSAP 单条 paused 时间轴)的快讯风竖屏短视频模板规范。

  • 中文名:快讯风竖屏短视频
  • 英文名:NewsFlash

用标题、副标题、视觉素材卡、正文分段四层结构呈现单条快讯:无旁白、无 BGM,靠文字级联入场、素材播放和待机氛围动效撑住节奏。


一、视频规格

项目规范
分辨率1080 × 1920(9:16 竖屏)
时长= 处理后素材片段的精确时长(ffprobe 实测),不固定区间、不额外加停留
帧率让时长为整数帧、源帧均匀映射(源 24fps × 1.5 → 36fps;否则 30 或 60fps)
格式.mp4(无音轨)
技术栈HyperFrames:单 index.html + GSAP 单条 paused 时间轴

#root 的 data-duration 与 data-fps 必须等于编码后素材片段的时长与帧率。


二、整体排版布局

<div id="root" data-composition-id="main"
  data-width="1080" data-height="1920"
  data-duration="20" data-fps="36">
  <!-- 背景装饰层 z-index: 0 -->
  <!-- .frame 内容列 z-index: 1 -->
  <!-- .vignette 暗角层 z-index: 2 -->
</div>
#root { position: relative; width: 1080px; height: 1920px; overflow: hidden; background: var(--bg); }
.frame {
  position: relative; z-index: 1;
  width: var(--content-w);   /* 880px */
  height: 100%; margin: 0 auto;
  display: flex; flex-direction: column; justify-content: center;
  text-align: center;
}

间距

项目值
标题 → 副标题12px
副标题 → 素材卡22px
素材卡 → 正文24px
正文行高1.45
正文段间距13px

出片前必须 snapshot 确认四层总高在 1920px 内;超高时先收紧间距,再按 2px 步进缩小正文字号。


三、配色与字体

3.1 配色(浅色纸感)

变量值用途
--bg#f7f3ea暖白纸感底色
--fg#202634标题主色
--fg-dim#5c6470副标题
--accent#8f5e00token 强调、正文高亮(浅底上满足 WCAG AA)
正文色#2c3240正文
--card-borderrgba(143, 94, 0, 0.28)素材卡描边

强调色取深色变体并通过对比度检查,不直接用素材亮色。

3.2 背景装饰

/* 柔焦暖色斑 ×2:右上金、左下橙 */
#blob-a { top: -280px; right: -260px;
  background: radial-gradient(circle, rgba(240, 205, 145, 0.55), transparent 68%); }
#blob-b { bottom: -300px; left: -280px;
  background: radial-gradient(circle, rgba(233, 178, 132, 0.4), transparent 68%); }

/* 两侧斜向金色细线,氛围循环中做透明度呼吸 */
#edge-a { top: 150px; left: -70px; transform: rotate(-33deg);
  background: linear-gradient(90deg, transparent, rgba(143, 107, 42, 0.85)); opacity: 0.28; }
#edge-b { bottom: 220px; right: -80px; transform: rotate(28deg);
  background: linear-gradient(90deg, transparent, rgba(143, 107, 42, 0.7)); opacity: 0.20; }

/* 极浅暖色暗角 */
.vignette { background: radial-gradient(ellipse at 50% 46%, transparent 58%, rgba(120, 100, 60, 0.18) 100%); }

3.3 字体:苹方内嵌 woff2

@font-face { font-family: "PingFang SC"; font-weight: 100 450;
  src: url("assets/fonts/PingFangSC-Regular.woff2") format("woff2"); }
@font-face { font-family: "PingFang SC"; font-weight: 451 550;
  src: url("assets/fonts/PingFangSC-Medium.woff2") format("woff2"); }
@font-face { font-family: "PingFang SC"; font-weight: 551 700;
  src: url("assets/fonts/PingFangSC-Semibold.woff2") format("woff2"); }

#root { font-family: "PingFang SC", sans-serif; }

四、文字层

4.1 字号与字重

元素字号字重颜色
标题62px,必须单行600--fg,强调 token 用 --accent
副标题43px400--fg-dim
正文38px500#2c3240,关键词 --accent

标题放不下一行时,用负 letter-spacing 和/或降字号(不低于约 54px)。

4.2 标题 token 化

标题按词拆成 .tk(inline-block,初始 opacity 0)供级联入场,1–2 个核心词加 .tk-ac:

<h1 id="title"
  ><span class="tk" id="tk1">Claude&nbsp;</span
  ><span class="tk tk-ac" id="tk2">4 行</span
  ><span class="tk" id="tk3">提示词,</span
  ><span class="tk" id="tk4">画出</span
  ><span class="tk tk-ac" id="tk5">人的一生</span></h1
>
#title { font-size: 62px; font-weight: 600; line-height: 1.26; color: var(--fg); }
.tk { display: inline-block; opacity: 0; will-change: transform; }
.tk-ac { color: var(--accent); }

4.3 副标题

一行完整句,概括看点,不与正文重复:

#subtitle {
  margin: 12px 0 0;
  font-size: 43px;
  font-weight: 400;
  line-height: 1.4;
  color: var(--fg-dim);
  opacity: 0;
}

4.4 正文

<div id="body-paras">
  <p>这段 30 秒动画<span class="hl">《人的一生》</span>,从一个细胞开始,到出生、长大、再孕育下一代,每一帧都是 Claude 用 JS 画的。</p>
  <p>一共写了两段提示词,加起来 <span class="hl">4 行</span>,思考力度拉满。</p>
  <p>整个过程跑了 2 小时,用掉 <span class="hl">2700 万 token</span>。</p>
</div>
#body-paras { margin: 0; text-align: left; width: 100%; }
#body-paras p {
  margin: 0;
  font-size: 38px;
  font-weight: 500;
  line-height: 1.45;
  color: #2c3240;
  opacity: 0;
  will-change: transform;
}
#body-paras p + p { margin-top: 13px; }
.hl { font-style: normal; color: var(--accent); }

文案来源

换行


五、素材层

5.1 素材处理(全部在 ffmpeg 完成)

(a) 高光拼接:按文案剪 2–4 段,拼成约 15s,再 1.5× → 约 10s。

ffmpeg -i source.mp4 -filter_complex \
  "[0:v]trim=2:7,setpts=PTS-STARTPTS[a];[0:v]trim=12:17,setpts=PTS-STARTPTS[b];[0:v]trim=24:29,setpts=PTS-STARTPTS[c];\
   [a][b][c]concat=n=3:v=1:a=0,setpts=PTS/1.5,fps=36[v]" \
  -map "[v]" -an -fps_mode cfr -c:v libx264 -crf 18 -pix_fmt yuv420p \
  -force_key_frames "expr:gte(t,n_forced*0.25)" -sc_threshold 0 assets/clip.mp4

(b) 整段原片:完整源片,按用户指定倍速(1× / 1.5× / 2×),不剪辑。

ffmpeg -i source.mp4 -vf "setpts=PTS/1.5,fps=36" \
  -an -fps_mode cfr -c:v libx264 -crf 18 -pix_fmt yuv420p \
  -force_key_frames "expr:gte(t,n_forced*0.25)" -sc_threshold 0 assets/clip.mp4

量时长与帧数(结果写入 data-duration / data-fps):

ffprobe -v error -select_streams v:0 -count_frames \
  -show_entries stream=duration,nb_read_frames,r_frame_rate -of default=nw=1 assets/clip.mp4

5.2 素材卡

.media-wrap { position: relative; margin: 22px 0 24px; width: 100%; opacity: 0; }
.card-glow {
  position: absolute; inset: -34px;
  background: radial-gradient(closest-side, rgba(230, 170, 80, 0.5), transparent 72%);
  opacity: 0.26; pointer-events: none;
}
.card-float { position: relative; z-index: 1; width: 100%; }
.media-card {
  overflow: hidden;
  border-radius: 20px;
  border: 1.5px solid var(--card-border);
  background: #fdfbf5;
}
.media-card video {
  display: block;
  width: 100%;
  aspect-ratio: 1920 / 1080;   /* = 源片比例 */
  object-fit: contain;
}
<video id="clip" src="assets/clip.mp4"
  data-start="0" data-duration="20"
  muted playsinline></video>

六、动效

6.1 原则

6.2 时间轴常量与节拍

var F = 1 / 36;            // 单帧时长 = 1 / data-fps
var T_CARD = 0;            // 素材卡
var T_TITLE = 0.1;         // 标题级联起点
var T_SUBTITLE = 0.62;     // 副标题
var T_BODY = 1.0;          // 正文首段
var BODY_GAP = 0.28;       // 正文段间隔
var T_AMBIENT = 0.5;       // 待机氛围起点
var AMBIENT_PERIOD = 3.2;  // 氛围呼吸周期
var COMP_DURATION = 20;    // = data-duration
节拍时刻动效
素材卡0sautoAlpha 1,scale 0.96 → 1,back.out(1.4),0.5s
标题级联0.10s 起锚点词 y70 / 0.16s,其余 y40–60 / 0.12–0.16s,相邻重叠 1 帧
副标题0.62sy34 → 0,0.38s
正文1.00s 起每段间隔 0.28s,y30 → 0,0.32s
待机氛围0.50s 起卡片 ±6px sin 浮动 + 辉光 / 细线透明度呼吸,周期 3.2s

6.3 关键代码

// 素材卡:无淡入、无位移,只做 scale 回弹
tl.set("#media-wrap", { autoAlpha: 1, scale: 0.96 }, T_CARD);
tl.to("#media-wrap", { scale: 1, duration: 0.5, ease: "back.out(1.4)" }, T_CARD);

// 标题 token 级联
var tokens = [
  { id: "#tk1", y: 70, d: 0.16 },
  { id: "#tk2", y: 60, d: 0.14 },
  { id: "#tk3", y: 52, d: 0.14 },
  { id: "#tk4", y: 46, d: 0.12 },
  { id: "#tk5", y: 40, d: 0.16 },
];
var t = T_TITLE;
tokens.forEach(function (k, i) {
  tl.set(k.id, { opacity: 1, y: k.y }, t);
  tl.to(k.id, { y: 0, duration: k.d, ease: "power4.out" }, t);
  t += k.d + (i === tokens.length - 1 ? 0 : -F);
});

// 副标题
tl.set("#subtitle", { opacity: 1, y: 34 }, T_SUBTITLE);
tl.to("#subtitle", { y: 0, duration: 0.38, ease: "power4.out" }, T_SUBTITLE);

// 正文按段入场
document.querySelectorAll("#body-paras p").forEach(function (el, i) {
  var at = T_BODY + i * BODY_GAP;
  tl.set(el, { opacity: 1, y: 30 }, at);
  tl.to(el, { y: 0, duration: 0.32, ease: "power4.out" }, at);
});

// 待机氛围(单一驱动,纯时间函数)
tl.to({}, {
  duration: COMP_DURATION - T_AMBIENT,
  ease: "none",
  onUpdate: function () {
    var w = (Math.PI * 2 / AMBIENT_PERIOD) * this.time();
    floatEl.style.transform = "translateY(" + (-6 * Math.sin(w)).toFixed(2) + "px)";
    glowEl.style.opacity = (0.26 + 0.08 * Math.sin(w + 1.1)).toFixed(3);
    edgeA.style.opacity  = (0.28 + 0.08 * Math.sin(w)).toFixed(3);
    edgeB.style.opacity  = (0.20 + 0.08 * Math.sin(w + Math.PI)).toFixed(3);
  },
}, T_AMBIENT);

window.__timelines = window.__timelines || {};
window.__timelines["main"] = tl;

七、校验与渲染

npx --yes hyperframes@0.8.27 lint                      # 快速反馈
npx --yes hyperframes@0.8.27 check                     # lint + 运行时 + 布局 + 对比度,需全绿
npx --yes hyperframes@0.8.27 snapshot --at 0 1.5 5 10  # 关键帧自检
npx --yes hyperframes@0.8.27 render                    # 出片 → renders/*.mp4

八、封面与首帧

封面从成片中取一帧,不另做设计。

N=540   # 选中帧序号 = 秒数 × fps
ffmpeg -i render.mp4 -vf "select=eq(n\,$N)" -frames:v 1 first_frame.png        # 9:16 完整帧
ffmpeg -i first_frame.png -vf "crop=1080:1440:0:240" cover_3x4.png             # 3:4 封面
ffmpeg -loop 1 -framerate $FPS -t 1 -i first_frame.png -i render.mp4 \
  -filter_complex "[0:v]format=yuv420p,setsar=1,fps=$FPS,trim=end_frame=1[a];[1:v]setsar=1[b];[a][b]concat=n=2:v=1:a=0[v]" \
  -map "[v]" -r $FPS -c:v libx264 -crf 16 -pix_fmt yuv420p -movflags +faststart final.mp4

九、速查表

想改什么改哪里值
时长 / 帧率#root 与 video 的 data-*= 素材片段实测时长 / 帧率
内容区宽--content-w880px(边距 100px)
标题#title62px / 600,单行(放不下:负字距或降至约 54px)
副标题#subtitle43px / 400,上间距 12px
正文#body-paras p38px / 500,行高 1.45,段间距 13px
素材卡间距.media-wrap 的 margin22px 0 24px
素材卡比例.media-card video 的 aspect-ratio= 源片比例,object-fit: contain
入场节拍T_* / BODY_GAP卡 0 / 标题 0.1 / 副标题 0.62 / 正文 1.0 / 段隔 0.28
氛围周期AMBIENT_PERIOD3.2s
配色--bg / --accent#f7f3ea / #8f5e00

十、Checklist

  1. 文案:根据来源帖写标题 / 副标题 / 正文,观点注明人名,提交用户审核通过。
  2. 素材:ffmpeg 按高光拼接或整段原片模式处理(倍速、去音轨、CFR、0.25s 关键帧),ffprobe 量视频流时长与帧数。
  3. 工程:搭 index.html;data-duration / data-fps 与素材一致;aspect-ratio 填源片比例。
  4. 字体:按文案用字从 PingFang.ttc 子集出三档 woff2,确认不缺字。
  5. 排版:标题拆 token 并单行;正文自然折行,消除孤字和半截短行;加 .hl。
  6. 校验:lint → check 全绿 → snapshot 确认四层不超 1920px → render。
  7. 复核:ffprobe 核对成片时长、帧率、无音轨。
  8. 封面:选高光帧,居中裁 3:4 出封面,并把该帧完整画面插为视频首帧(1 帧)。

本文档为快讯风竖屏短视频(NewsFlash)模板的设计与开发规范,参数与流程自包含于本文。


上一篇
黑板长卷短视频 · 制作流程手册(一镜到底 · 无限画布)
下一篇
杂志撕纸风 Motion Graphics · 制作流程手册(Magazine Collage MG)