# 用 HyperFrames + GPT-image-2 制作母亲节视频:技术人的浪漫表达
昨天晚上 11 点多,突然想起来今天是母亲节,想做点什么。
本来已经准备睡了,但脑子里转了一下——用代码传递情感,用技术表达温度,这事儿好像挺有意思的。
一开始尝试用即梦的 Seedance 2.0 和 Coze 分别做了视频,但效果都不理想——要么动作僵硬,要么风格不稳定,反复调了几版都没达到预期。
后来静下心来想,既然要表达情感,画面质量必须过关。想到了最近一直高频使用的 HyperFrames,再配上最近效果最好的 GPT-image-2 文生图,思路一下子清晰了。
整理了一下大概的方向,折腾了差不多半小时,终于把这个视频做出来了。趁记忆新鲜,把制作过程记录下来,供有同样想法的朋友参考。
之前用过几个文生图工具,Stable Diffusion、Midjourney、DALL-E,各有特点。但这次有个特殊需求:风格统一。
母亲节视频不是一张图,是一组图——开场、配图、结尾,每张都要有统一的视觉风格。以前用 Midjourney 的时候,靠 seed 控制,但用起来总是不太稳定,同一个 prompt 跑出来的图色调、构图经常有差异。
这次试了 OpenAI 的 GPT-image-2(ChatGPT 4o 的图像生成能力),效果出乎意料。关键优势:
1. 风格一致性极强
同一个对话里连续生成多张图,角色一致性很高。面孔、配色、构图风格基本一致,不会有"这是同一个人吗"的问题。
2. 自然语言控制
直接用自然语言描述你要什么,不用记一堆参数。中文理解也很准确。
3. 响应速度快
比大多数云端图生图服务快,生成一张图通常 10-20 秒。
在开始生成之前,先想清楚整个视频的视觉调性。
母亲节视频,我定义的风格是:温暖、柔和、真诚。不用太炫酷的特效,色调偏暖黄和粉色系,构图简洁,主体突出。
每个 prompt 前面都加了一句统一的风格描述:
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。
后续的每一张图,都在这个基础上描述具体内容。
确定风格后,按视频顺序逐张生成。以下是我实际用过的 10 个 prompt:
【开场海报】对应旁白:"他们说,我是你九死一生换来的宝贝。可你看向我的那一刻,却笑着像得到了全世界。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。生成一张海报,内容如下:我曾是你九死一生换来的宝贝,也是你往后余生唯一的软肋。你拉着我的手学会走路,把伞歪向我这边淋湿了肩,你陪我熬过无数个刷题的深夜,目送我一次次离开,又笑着等我回来。妈,今天我不想当大人。母亲节快乐,我最勇敢的超人 ❤️——谨以此片,献给全天下每一位妈妈。
【场景1】对应旁白:"1岁时,我跌跌撞撞走向你,你张开的手臂,是我人生第一个确信的终点。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。幼儿仰视视角,年轻的妈妈蹲在前方张开双臂,微笑鼓励,逆光形成金色轮廓光,午后温暖阳光,木地板上有人影,柔软治愈,高细节。
【场景2】对应旁白:"后来,每一个雨天,伞总是歪向我这边。你淋湿的肩膀,成了我晴天的屋檐。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。孩子透过雨水的视角,校门口,妈妈撑着透明雨伞蹲下迎接,伞倾向镜头,母亲肩膀淋湿,水洼倒映暖黄路灯,治愈雨景,绘本风格,高细节。
【场景3】对应旁白:"那些熬夜刷题的晚上,你什么都不说,只是一次次热好牛奶,陪我到很晚很晚。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。第一人称视角写作业,台灯暖光,一只手轻轻放下一杯热牛奶,牛奶冒热气,桌上试卷和书本,背景昏暗有便利贴,温暖静谧,高画质。
【场景4】对应旁白:"离开家的那天,你笑着挥手,我假装没看见,你转身时擦掉的眼角。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。透过火车车窗视角,站台上妈妈挥手告别,笑容带泪,隐约白发,晨光逆光,微颗粒感,电影感,温暖又感伤,高细节。
【场景5】对应旁白:"大学里,每次挂掉电话,我都在想,你肯定又对着屏幕唠叨了很久,哪怕我早已按下了静音键。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。第一人称手持手机视频通话,屏幕里妈妈笑容温暖,背景是家中沙发,屏幕外宿舍床沿,连接光束,现代温情,高画质。
【场景6】对应旁白:"工作后每次回家,开门的瞬间,你眼里的光,让我知道,我永远是被期待的。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。推门入户的第一人称视角,妈妈系着围裙惊喜迎来,手上沾面粉,厨房热气,暖黄灯光,温馨扑面,高画质。
【场景7】对应旁白:"今天,我不想长大,只想赖在你怀里,再当一回小孩。妈,母亲节快乐,我最勇敢、最温柔的超人。"
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。温暖治愈绘本风格,暖黄午后阳光,成年孩子与头发花白的妈妈幸福拥抱,妈妈的脸轻靠在孩子肩头,眼带泪光微笑,孩子双手环抱着母亲,背景是温馨的客厅或窗边,画面充满爱与感恩,高画质,右上适当留白。
【场景8】无旁白,静默展示
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。9:16比例,统一温暖治愈绘本风,婴儿主观视角,镜头微微模糊,画面中央是一位25岁年轻亚洲妈妈温柔的笑脸,黑色长发垂落,眼神充满爱意,背景是柔和的产房灯光,暖奶油色调,梦幻柔焦,治愈系绘本风格,高画质。
【结尾图】无旁白,静默展示
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。画面中央是一束盛开的粉色康乃馨,柔和的金色晨光从侧面洒落,花瓣上带着晶莹露珠。背景虚化处理,可见朦胧的暖黄色光斑,如家的灯光。花朵下方,优雅的白色手写体中文浮现:"祝全天下母亲节日快乐,您辛苦了!在我心中您永远年轻!"。整体色调温暖治愈,电影感光影,高画质。
关键技巧:每个 prompt 前面都统一加上风格描述(9:16竖屏构图、温馨的母亲节主题插画、温暖治愈色调、电影感光影),保证全系列风格一致。后续图片在已生成的图片基础上微调,比如"与之前生成的图X风格一致"。
┌─────────────────────────┐
│ 开场海报(4秒) │
│ 诗歌文案 + 标题 │
└─────────────────────────┘
┌─────────────────────────┐
│ 场景1(幼儿仰视妈妈)│
│ 场景2(雨伞接孩子) │
│ 场景3(深夜送牛奶) │
│ 场景4(车站送别) │
│ 场景5(视频通话) │
│ 场景6(推门回家) │
│ 场景7(母子拥抱) │
│ 场景8(妈妈笑脸) │
└─────────────────────────┘
┌─────────────────────────┐
│ 结尾康乃馨(3秒) │
│ 静默 + "母亲节快乐" │
└─────────────────────────┘
总时长约 90 秒。
mothers-day/
├── index.html # 主 composition
├── music.mp3 # 背景音乐
├── pic/ # 图片素材
│ ├── poster.png # 开场海报
│ ├── scene1.png # 幼儿仰视妈妈
│ ├── scene2.png # 雨伞接孩子
│ ├── scene3.png # 深夜送牛奶
│ ├── scene4.png # 车站送别
│ ├── scene5.png # 视频通话
│ ├── scene6.png # 推门回家
│ ├── scene7.png # 母子拥抱
│ ├── scene8.png # 妈妈笑脸
│ └── ending.png # 结尾康乃馨
└── content.md # 文案存档
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1080, height=1920" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body {
margin: 0;
width: 1080px;
height: 1920px;
overflow: hidden;
background: linear-gradient(135deg, #FFF5F7 0%, #FFE4EC 50%, #FFF0F5 100%);
font-family: "PingFang SC", "Microsoft YaHei", sans-serif;
}
.scene-content {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
.poster-area,
.scene-area,
.ending-area {
position: absolute;
top: 0;
left: 0;
width: 1080px;
height: 1920px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80px 60px;
}
.scene-img {
max-width: 90%;
max-height: 85%;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0,0,0,0.12);
position: absolute;
opacity: 0;
object-fit: cover;
}
.poster-text {
position: absolute;
bottom: 120px;
font-size: 36px;
line-height: 1.8;
color: #FFFFFF;
text-align: center;
padding: 40px;
background: linear-gradient(to top, rgba(0,0,0,0.7), transparent);
width: 100%;
left: 0;
right: 0;
}
.subtitle-area {
position: absolute;
bottom: 260px;
left: 0;
right: 0;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.subtitle {
font-size: 42px;
font-weight: 600;
color: #FFFFFF;
text-align: center;
padding: 20px 36px;
background: rgba(233, 30, 99, 0.88);
border-radius: 14px;
opacity: 0;
text-shadow: 0 2px 8px rgba(0,0,0,0.3);
box-shadow: 0 8px 32px rgba(233, 30, 99, 0.35);
max-width: 88%;
line-height: 1.6;
}
.ending-text {
position: absolute;
bottom: 160px;
font-size: 48px;
font-weight: 700;
color: #FFFFFF;
text-align: center;
padding: 28px 48px;
background: rgba(233, 30, 99, 0.9);
border-radius: 16px;
text-shadow: 0 2px 8px rgba(0,0,0,0.3);
}
</style>
</head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-duration="32" data-width="1080" data-height="1920">
<div class="scene-content">
<!-- 开场海报 -->
<div class="poster-area" id="poster">
<img class="scene-img" id="poster-img" src="./pic/poster.png" alt="开场" />
<div class="poster-text">妈妈,我爱你 ❤️</div>
</div>
<!-- 场景轮播 -->
<div class="scene-area" id="scenes">
<img class="scene-img" id="s1" src="./pic/scene1.png" alt="幼儿仰视妈妈" />
<img class="scene-img" id="s2" src="./pic/scene2.png" alt="雨伞接孩子" />
<img class="scene-img" id="s3" src="./pic/scene3.png" alt="深夜送牛奶" />
<img class="scene-img" id="s4" src="./pic/scene4.png" alt="车站送别" />
<img class="scene-img" id="s5" src="./pic/scene5.png" alt="视频通话" />
<img class="scene-img" id="s6" src="./pic/scene6.png" alt="推门回家" />
<img class="scene-img" id="s7" src="./pic/scene7.png" alt="母子拥抱" />
<img class="scene-img" id="s8" src="./pic/scene8.png" alt="妈妈笑脸" />
</div>
<!-- 字幕 -->
<div class="subtitle-area">
<div class="subtitle clip" data-start="4" data-duration="3.2" data-track-index="10">他们说,我是你九死一生换来的宝贝。<br/>可你看向我的那一刻,<br/>却笑着像得到了全世界。</div>
<div class="subtitle clip" data-start="7.5" data-duration="3.2" data-track-index="11">1岁时,我跌跌撞撞走向你,<br/>你张开的手臂,<br/>是我人生第一个确信的终点。</div>
<div class="subtitle clip" data-start="11" data-duration="3.2" data-track-index="12">后来,每一个雨天,<br/>伞总是歪向我这边。<br/>你淋湿的肩膀,成了我晴天的屋檐。</div>
<div class="subtitle clip" data-start="14.5" data-duration="3.2" data-track-index="13">那些熬夜刷题的晚上,你什么都不说,<br/>只是一次次热好牛奶,<br/>陪我到很晚很晚。</div>
<div class="subtitle clip" data-start="18" data-duration="3.2" data-track-index="14">离开家的那天,你笑着挥手,<br/>我假装没看见,<br/>你转身时擦掉的眼角。</div>
<div class="subtitle clip" data-start="21.5" data-duration="3.2" data-track-index="15">大学里,每次挂掉电话,<br/>我都在想,你肯定又对着屏幕<br/>唠叨了很久。</div>
<div class="subtitle clip" data-start="25" data-duration="3.2" data-track-index="16">工作后每次回家,<br/>开门的瞬间,你眼里的光,<br/>让我知道,我永远是被期待的。</div>
<div class="subtitle clip" data-start="28.5" data-duration="3.2" data-track-index="17">今天,我不想长大,<br/>只想赖在你怀里,再当一回小孩。<br/>妈,母亲节快乐!</div>
</div>
<!-- 结尾 -->
<div class="ending-area" id="ending">
<img class="scene-img" id="ending-img" src="./pic/ending.png" alt="结尾" />
<div class="ending-text">祝全天下母亲节日快乐 ❤️</div>
</div>
</div>
</div>
<!-- 背景音乐 -->
<audio id="bgm" data-start="0" data-duration="32" data-track-index="99" src="./music.mp3" data-volume="0.2"></audio>
<script>
window.__timelines = window.__timelines || {};
const tl = gsap.timeline({ paused: true });
const totalDuration = 32;
// 海报入场
tl.fromTo("#poster-img",
{ opacity: 0, scale: 0.9 },
{ opacity: 1, scale: 1, duration: 1.5, ease: "power3.out" },
0.5);
tl.to("#poster", { opacity: 0, duration: 0.8 }, 3.5);
// 场景轮播(每张图展示3秒,间隔0.3秒过渡)
const sceneIds = ["#s1","#s2","#s3","#s4","#s5","#s6","#s7","#s8"];
sceneIds.forEach((id, i) => {
const start = 4.3 + i * 3;
tl.fromTo(id,
{ opacity: 0, scale: 0.95 },
{ opacity: 1, scale: 1, duration: 0.5, ease: "power2.out" },
start);
if (i < sceneIds.length - 1) {
tl.to(id,
{ opacity: 0, duration: 0.4, ease: "power2.in" },
start + 2.6);
}
});
// 字幕动画
const subs = [
{ s: 4, id: "#subtitle1" },
{ s: 7.5, id: "#subtitle2" },
{ s: 11, id: "#subtitle3" },
{ s: 14.5, id: "#subtitle4" },
{ s: 18, id: "#subtitle5" },
{ s: 21.5, id: "#subtitle6" },
{ s: 25, id: "#subtitle7" },
{ s: 28.5, id: "#subtitle8" }
];
subs.forEach(sub => {
tl.fromTo(sub.id,
{ opacity: 0, y: 20 },
{ opacity: 1, y: 0, duration: 0.4 },
sub.s);
tl.to(sub.id,
{ opacity: 0, duration: 0.35 },
sub.s + 2.85);
});
// 结尾入场
tl.fromTo("#ending-img",
{ opacity: 0, scale: 0.9 },
{ opacity: 1, scale: 1, duration: 1.2 },
28.5);
// 背景音乐
tl.call(() => {
const bgm = document.querySelector("#bgm");
if (bgm) { bgm.volume = 0.2; bgm.play(); }
}, [], 0);
window.__timelines["main"] = tl;
</script>
</body>
</html>
1. 统一风格前缀
每个 prompt 前面都加相同的风格描述,保证 10 张图风格高度统一:
9:16竖屏构图,温馨的母亲节主题插画。整体色调温暖治愈,电影感光影,高画质。
2. 海报开场
开场用一张诗歌文案海报,配上"妈妈,我爱你 ❤️"的主标题,视觉冲击力强。
3. 场景平滑过渡
每张图展示约 2.6 秒,淡入淡出间隔 0.4 秒,过渡自然不跳切。
4. 旁白字幕较长,用 <br/> 换行
每条旁白文案较长,在 HTML 里用 <br/> 手动换行,控制每行长度,保证阅读体验。
5. 背景音乐
音量固定 0.2,烘托气氛不抢戏。
cd mothers-day
# 检查语法
npx hyperframes lint .
# 预览
npx hyperframes preview --port 3002
# 渲染
npx hyperframes render --duration 32 --output output.mp4 --quality standard
坑1:图生图的风格不一致
- 原因:分开多次生成,每次都像抽卡
- 解决:每个 prompt 前面统一加风格前缀(9:16竖屏构图、温暖治愈色调、电影感光影),保证全系列一致
坑2:字幕太长换行乱
- 原因:字幕 text 直接放进去,长句子不会自动换行
- 解决:用 <br/> 手动换行,控制每行长度在 15 字以内
坑3:背景色和图片冲突
- 原因:有些图的背景偏白,和渐变背景融在一起
- 解决:CSS 渐变背景用偏暖的粉色系,和大多数图都能搭配;图片加 box-shadow 产生立体感
今天母亲节,用不到两小时做了这个视频,技术上没什么难度,但做的时候心里挺暖的。
程序员这个群体很多时候被贴上"不懂浪漫"的标签,但其实浪漫不浪漫,跟职业无关,跟有没有心有关。
用代码传递情感,用技术表达温度,这大概是我能想到的最 geek、也最真诚的方式了。
最后,祝全天下所有的母亲——节日快乐!
你在母亲节做了什么有意思的事?有没有用技术表达情感的经历?欢迎评论区分享。
💬 评论区