Moments Memoir — 朋友圈个人回忆录(时光簿)
将一个人的朋友圈内容,转化为一份有温度、有设计感、让人心颤的个人回忆录。
这不是日报,不是流水账。是一本翻开就舍不得合上的时光簿。
触发条件
当用户提到以下内容时触发:
- "朋友圈回忆录"、"时光簿"、"个人朋友圈总结"、"年度朋友圈回忆"
- "帮我把朋友圈做成回忆录"
- 上传了某人的朋友圈录屏/截图,并要求做个人回忆(而非日报)
与 moments-digest(朋友圈日报)的区别:
- 日报 = 多人、当日、客观总结、信息导向
- 回忆录 = 单人、长周期、散文叙事、情感导向
核心原则(铁律,不可违反)
1. 主题聚合叙事,绝不按时间线流水账
分析完所有朋友圈内容后,提炼出 3-5 个主题维度(如山河、柔软、热爱、有趣等),将内容按主题归类后以散文笔法叙述。
主题不固定、不死套模板。每个人的朋友圈不同,主题划分要因人而异——从素材中自然生长,体现独立思考。
2. 叙事风格:散文式,精简不啰嗦,情绪价值拉满
情绪价值是这份回忆录的灵魂。 读者(通常是朋友圈的主人本人)看完应该有"回忆满满、感动常在"的感觉——这是最核心的衡量标准。
- 触动心灵的地方要写深——用意象、比喻、留白让人心颤
- 幽默处带温度,悲伤处留余韵,骄傲处不炫耀,告别处要克制
- 金句从细节中自然生长,不贴鸡汤
- 每一段叙事都要从朋友圈的具体内容出发,不能空泛抒情
- 工作/职业相关的叙事,要突出团队协作的价值,而非个人英雄主义
- 家庭相关的叙事,要关注所有家庭成员(伴侣、孩子、父母),不遗漏
- 所有叙事须贴合中国文化(见核心原则第4条):含蓄内敛、重关系重感恩、避免西式鸡汤
3. 视觉风格:固定微信风格配色
配色方案固定为微信风格,因为最终产出物是在微信朋友圈发表的长图,微信风格配色最为贴合:
- 主色:微信绿
#07C160,封面用绿色渐变背景 + 白色文字 - 正文区:白色背景
#FFFFFF+ 深灰文字#191919/#3b3b3b,浅灰分割线 - 强调色:微信绿用于标题标签、年份标记、引用框左边框、高亮文字
- 卡片/统计区:浅灰底
#F7F7F7+ 浅边框,圆角卡片 - 链接/交互元素:微信蓝
#576B95(可选) - 整体风格:明亮、清新、温暖怀旧,像微信官方产品页面
此配色为铁律,不可更改。 排版、字体、动画仍可根据内容灵活调整,但色调体系必须保持微信风格。
4. 文化基调:避免个人英雄主义,贴合中国文化
内容生成必须贴合中国文化语境,具体要求:
- 避免个人英雄主义叙事:不突出"我一个人做到了",而是强调"我们一起走过了"。成就归团队,温暖归家庭,成长归经历
- 集体主义底色:工作叙事体现团队协作、战友情谊;家庭叙事体现天伦之乐、薪火相传;朋友叙事体现知己难得、相互成就
- 含蓄内敛:中国人的骄傲是藏在细节里的,不直接说"我很厉害",而是用事实和细节让读者自己感受到
- 重关系、重感恩:叙事中自然流露对身边人的感恩——父母的付出、伴侣的支持、团队的信任、朋友的陪伴
- 人情味:中国式的人情世故是温暖的底色——过年回家、同事聚餐、老友重逢,这些都值得被温柔对待
- 避免西式鸡汤和成功学话术:不用"追随你的心"、"成为最好的自己"之类的翻译腔,要用有中国味道的表达
此为铁律,不可违反。 回忆录的受众是朋友圈好友,中国文化语境下的表达最能引起共鸣。
5. 署名统一
所有输出的署名统一为:loap's claw
输出结构
A. 朋友圈长图(主交付物)
封面
└─ 朋友圈 Logo(微信朋友圈相机图标 SVG)
└─ 昵称
└─ 标题(如"朋友圈回忆录")
└─ 副标题(一句抓人的引言)
└─ 时间跨度
└─ 数据概览(紧凑横条:N条朋友圈 / N座城市 / N个年头等)
分割线
主题叙事章节 × 3~5 个(壹/贰/叁/肆/伍)
└─ 每章结构:
├─ chapter-label(中文数字 + 篇名)
├─ 标题(提炼主题精髓的短句)
├─ 副标题(辅助解读的一句话)
├─ prose 叙事段(散文正文,引用朋友圈原文加高亮)
└─ pull-quote 金句(从叙事中提炼的点睛之笔)
足迹地图(默认生成)
└─ 在识别朋友圈内容时,**主动提取所有地点信息**
└─ SVG 中国地图 + 标注城市 + 脉冲打点动画
└─ 如涉及海外城市,在地图边缘标注海外方向
└─ 城市列表卡片
└─ **注意**:仅当识别到的独立城市少于 3 个时,才可跳过此板块
朋友圈精选卡片
└─ 2列网格
└─ 每张卡片:emoji + 地点/事件标识(不用日期)+ 标题 + 1-2句精华描述
└─ 关键词高亮
尾声
└─ 回顾性总结段落
└─ 呼应全文最动人的细节
└─ 最后一句留温暖余韵
└─ 署名:—— loap's claw · YYYY年M月 ——
B. 小红书系列图文(附加交付物)
在完成朋友圈长图后,额外生成一套适合在小红书发布的图文系列。
B.1 设计规范
- 尺寸:每张图
1080 × 1440px(3:4竖屏),截图 DPR=2,输出2160 × 2880px - 配色:沿用微信风格配色(与朋友圈长图一致)
- 每页一个主题,内容必须撑满整页,不留大面积空白
- 页码:右上角标注
N/总页数 - 底部签名:
loap's claw+ 页码
B.2 内容拆分规则
将回忆录内容按故事节奏拆分为 5~9 张图,遵循以下结构:
图1 — 封面页
└─ 绿色渐变背景 + 白色大标题
└─ 钩子标题(让人想看下去的一句话)
└─ 时间跨度、数据概览(N条朋友圈 / N座城市 / N年)
└─ "向右滑动 →" 提示
图2~N-1 — 主题内容页(每个回忆录章节对应一页)
└─ 每页:chapter-tag + 大标题 + 副标题
└─ 内容形式灵活:
- 时间轴卡片(适合职业/成长类主题)
- 卡片式年份流(适合家庭/成长类主题)
- SVG 足迹地图 + 城市标签(适合旅行/山河类主题)
- 语录卡片组 + 数据面板(适合兴趣/热血类主题)
- 2列 emoji 卡片网格(适合段子/有趣类主题)
└─ 底部 quote-box 金句
└─ **铁律:内容必须撑满 1440px 高度**
- 使用 `flex:1` + `justify-content:space-between` 让内容垂直均匀分布
- 如内容不够多,增加引用卡片、数据摘要面板、或从素材中补充更多细节
- 绝不允许下半页留白超过 200px
图N — 尾声页
└─ 绿色渐变背景 + 白色文字
└─ 散文式收尾(呼应开头,回望全文最动人的细节)
└─ 最后一句留温暖余韵
└─ 署名
B.3 撑满页面的技巧(铁律)
每张内容页必须视觉上撑满 1440px,避免空白。具体手法:
- 外层容器:
.body-text { flex:1; display:flex; flex-direction:column; justify-content:space-between; } - 时间轴/卡片:用
space-between让多个卡片均匀分布 - 内容不够时:
- 增加一个 "数据摘要面板"(如 "球迷生涯一览:15年英格兰球迷 / 1届世界杯保障")
- 增加更多引用卡片(从素材中挖掘未被收录的有趣内容)
- 增加装饰性元素(分隔线、emoji行等)
- 字号可适当放大:内容页标题 52px,正文 25-26px,卡片内文 24-25px
B.4 文案生成
为每张图生成对应的小红书发布文案:
## 📱 图N — xhs_0N.png
**标题:** 一句吸引点击的标题
**正文:**
正文内容(200字以内)
引用朋友圈原文加引号
带情绪但不煽情
结尾带emoji
#标签1 #标签2 #标签3 #标签4 #标签5
文案要求:
- 标题:口语化、有钩子,让人想点进来(如"翻了翻朋友圈,发现自己已经待了快十年")
- 正文:200字以内,带原文引用,有节奏感,适合手机阅读
- 标签:5-8个,覆盖主题词(朋友圈回忆录/行业词/情感词)
- 发布建议:最后附上发布时间、互动引导等建议
B.5 小红书 HTML 模板规范
生成一个多页 HTML 文件(xhs_pages.html),每页用 .page 类包裹:
.page {
width: 1080px;
height: 1440px;
position: relative;
overflow: hidden;
page-break-after: always;
}
关键 CSS 规则:
- 每页固定
1080 × 1440px,overflow:hidden裁剪溢出 - 封面/尾声:绿色渐变背景,
display:flex; align-items:center; justify-content:center - 内容页:白色背景,
padding: 64px 72px 48px - 使用
id="page1"~id="pageN"标识每页,便于 Puppeteer 逐页截图
B.6 截图脚本
使用 scripts/capture_xhs_pages.js 逐页截图:
// 核心逻辑:遍历每个 .page 元素,逐个截图
for (let i = 1; i <= totalPages; i++) {
const el = await page.$(`#page${i}`);
await el.screenshot({ path: `xhs_${String(i).padStart(2, '0')}.png`, type: 'png' });
}
参考调用:
NODE_PATH=/Users/loapli/.workbuddy/binaries/node/workspace/node_modules \
/Users/loapli/.workbuddy/binaries/node/versions/22.12.0/bin/node \
~/.workbuddy/skills/moments-memoir/scripts/capture_xhs_pages.js \
--html "<xhs_pages.html路径>" \
--out-dir "<输出目录>"
完整工作流程
第一步:素材获取
检查用户上传的文件类型:
A. 视频录屏(.mp4, .mov, .avi, .mkv)
使用 moments-digest Skill 中的抽帧脚本:
# 确保依赖已安装
/usr/bin/python3 -m pip install --user opencv-python-headless imagehash pillow
# 抽帧
/usr/bin/python3 ~/.workbuddy/skills/moments-digest/scripts/process_video.py \
--video "<视频文件路径>" \
--output "<输出目录>" \
--mode "annual" \
--max-frames 80
然后用 read_file 逐张读取抽帧图片进行 AI 识别。
B. 截图(.png, .jpg, .jpeg, .webp)
直接用 read_file 读取图片进行 AI 识别。
C. 已整理的文字素材
如果用户直接提供了文字版的朋友圈内容列表,跳过图片识别步骤。
第二步:内容识别与提取
对每张图片/帧,识别并提取:
- author: 发布者昵称
- content: 文字内容(原文)
- images_description: 图片描述
- timestamp_text: 时间文本
- location: 位置信息(重点提取——即使朋友圈未显式标注,也要从图片内容、文字提及的城市/景点/餐厅名推断地点)
- category: 分类(旅行/家庭/工作/美食/兴趣/感悟/社交/转发/广告/其他)
- mood: 情绪倾向
- highlights: 亮点或有趣之处
- comments: 评论(如有)
地点提取铁律:在内容识别阶段就要尽可能多地提取地点信息,因为后续需要生成足迹打点地图。即使文字中只是提到"去了XXX"、图片里出现地标建筑,也要记录为地点。
去重规则:同一作者 + 内容前30字相同 = 重复,保留更清晰的那条。
第三步:素材分析与主题提炼
这是最关键的一步。
- 通读所有提取的内容,感受这个人的气质、性格、生活状态
- 提炼 3~5 个主题维度
- 不要用固定模板!从素材中自然生长
- 例如一个旅行达人可能是:远方/味蕾/家/信仰/玩心
- 例如一个技术人可能是:山河/柔软/热爱/有趣
- 将每条朋友圈归入对应主题
- 确定视觉风格方案——固定为微信风格配色(见核心原则第3条),排版/动画可灵活调整
- 统计数据:总条数、涉及城市、时间跨度等
第四步:撰写回忆录文案
按照输出结构 A撰写全部文案。核心要求:
- 封面副标题:一句能让人停下来的话
- 每章 prose:从朋友圈原文出发,用散文笔法串联,加入观察和感悟。引用原文用高亮标记
- 每章 pull-quote:从叙事中自然提炼的金句,要有力、有画面感、不鸡汤
- 尾声:回望全文最动人的细节,最后一句留温暖余韵
第五步:生成朋友圈 HTML
生成单页自包含 HTML 文件,要求:
- 自包含:所有 CSS/JS 内联,不依赖外部文件(Google Fonts 除外)
- 页面宽度 1080px:适配长图截图
- 字号体系(1080px 宽度下):
- 封面标题:36-42px
- 章节标题:22-26px
- 正文 prose:15-18px
- 金句 quote:14-16px
- 卡片标题:14-16px
- 卡片描述:12-14px
- 间距紧凑:section 间距 16px,内部 padding 28-36px
- 交互动画:IntersectionObserver 实现滚动渐入(.reveal 类)
- SVG 足迹地图(默认生成):用 SVG 绘制中国简版地图 + 城市标注 + 脉冲打点动画。仅当独立城市少于 3 个时可跳过
- 总高度控制:优先控制在 1080 × 3500~8000px;内容较多时允许更长,但必须使用分片拼接导出,确保无重复无缺失
第六步:截图生成朋友圈长图 PNG(默认分片拼接方案)
默认使用"分片截图 + 无损拼接",不要优先使用超长 fullPage: true 一次性截图。
原因:当页面很长且使用高 DPR(尤其 3x)时,Chromium 可能出现循环拼接渲染,导致内容重复或缺失。
6.1 截图前拍平页面动态状态
在截图前必须执行以下处理:
- 强制显示
.reveal区块(补齐滚动触发内容) - 关闭全局动画和过渡(避免中间态)
- 移除
scroll-hint - 覆盖 cover 的
min-height: 100vh和::before超大伪元素影响
6.2 分片截图参数(固定建议)
viewport width: 1080deviceScaleFactor: 2(默认)- 分片高度:
1200~1400CSS px - 纵向切片顺序命名:
tile_000.png,tile_001.png...
6.3 Puppeteer 分片截图参考
const puppeteer = require('puppeteer');
const browser = await puppeteer.launch({ headless: 'new' });
const page = await browser.newPage();
await page.setViewport({ width: 1080, height: 1200, deviceScaleFactor: 2 });
await page.goto('file://' + htmlPath, { waitUntil: 'networkidle0', timeout: 60000 });
await page.evaluate(() => document.fonts.ready);
await page.evaluate(() => {
document.querySelectorAll('.reveal').forEach((el) => el.classList.add('visible'));
const hint = document.querySelector('.scroll-hint');
if (hint) hint.remove();
});
await page.addStyleTag({
content: `
*, *::before, *::after { animation: none !important; transition: none !important; }
.reveal { opacity: 1 !important; transform: none !important; }
.cover { min-height: auto !important; height: auto !important; overflow: hidden !important; }
.cover::before { display: none !important; }
`,
});
const totalHeight = await page.evaluate(() => document.body.scrollHeight);
const tileHeight = 1400;
for (let y = 0, i = 0; y < totalHeight; y += tileHeight, i += 1) {
const h = Math.min(tileHeight, totalHeight - y);
await page.screenshot({
path: `${outputDir}/tile_${String(i).padStart(3, '0')}.png`,
type: 'png',
captureBeyondViewport: true,
clip: { x: 0, y, width: 1080, height: h },
});
}
await browser.close();
6.4 Python 无损拼接参考
from PIL import Image
import glob
tiles = sorted(glob.glob(f"{tile_dir}/tile_*.png"))
imgs = [Image.open(p) for p in tiles]
canvas = Image.new("RGB", (imgs[0].width, sum(i.height for i in imgs)), "white")
y = 0
for im in imgs:
canvas.paste(im, (0, y))
y += im.height
canvas.save(output_png, "PNG")
6.5 导出策略铁律
- 默认优先:分片截图 + 拼接(DPR=2)
- 明确禁忌:在超长页面上优先使用
DPR=3 + fullPage: true - 仅当用户明确指定时,才尝试一次性 fullPage 方案
6.6 优先调用本 Skill 内置脚本
优先复用以下脚本,而不是每次临时重写:
scripts/capture_tiled_fullpage.js:执行分片截图(朋友圈长图)scripts/stitch_tiles.py:执行无损拼接(朋友圈长图)scripts/capture_xhs_pages.js:执行小红书逐页截图
参考调用:
# 1) 朋友圈长图 - 分片截图
NODE_PATH=/Users/loapli/.workbuddy/binaries/node/workspace/node_modules \
/Users/loapli/.workbuddy/binaries/node/versions/22.12.0/bin/node \
~/.workbuddy/skills/moments-memoir/scripts/capture_tiled_fullpage.js \
--url "http://localhost:8877/memoir.html" \
--out-dir "/tmp/memoir-tiles" \
--width 1080 \
--tile-height 1400 \
--dpr 2
# 2) 朋友圈长图 - 无损拼接
/usr/bin/python3 ~/.workbuddy/skills/moments-memoir/scripts/stitch_tiles.py \
--tiles-dir "/tmp/memoir-tiles" \
--output "/tmp/memoir.png"
# 3) 小红书系列图 - 逐页截图
NODE_PATH=/Users/loapli/.workbuddy/binaries/node/workspace/node_modules \
/Users/loapli/.workbuddy/binaries/node/versions/22.12.0/bin/node \
~/.workbuddy/skills/moments-memoir/scripts/capture_xhs_pages.js \
--html "<xhs_pages.html文件路径>" \
--out-dir "<输出目录>"
确保 Puppeteer 已安装:
cd /Users/loapli/.workbuddy/binaries/node/workspace && /Users/loapli/.workbuddy/binaries/node/versions/22.12.0/bin/npm install puppeteer
第七步:生成小红书图文
在完成朋友圈长图后,按照输出结构 B 生成小红书系列图文:
- 拆分内容:将回忆录按故事节奏拆分为 5~9 页
- 生成 HTML:创建
xhs_pages.html,每页 1080×1440px,内容撑满 - 截图:使用
capture_xhs_pages.js逐页截图 - 生成文案:为每张图写对应的小红书发布文案,输出为
文案.md
第八步:交付(全套交付物)
以下交付物缺一不可:
| 交付物 | 格式 | 用途 |
|-------|------|------|
| 朋友圈回忆录 HTML | .html | 在线预览和二次编辑 |
| 朋友圈长图 | .png | 直接发微信朋友圈 |
| 小红书系列图 | xhs_01.png ~ xhs_0N.png | 直接发小红书 |
| 小红书文案 | 文案.md | 每张图对应的发布文案 |
交付流程:
- 用
preview_url预览朋友圈 HTML 文件 - 用
deliver_attachments交付全部文件 - 文字版回复中简要说明主题划分思路和设计选择
- 提醒用户:
- PNG 长图可直接保存到手机发朋友圈
- 小红书图文建议 7 张一起发,标题用封面标题
- 建议发布时间:工作日晚上 20:00-22:00 或周末下午
质量检查清单
朋友圈长图
- [ ] 是否按主题聚合而非时间线?
- [ ] 主题是否从素材自然生长而非套用固定模板?
- [ ] 叙事是否基于朋友圈原文而非空泛抒情?
- [ ] 金句是否从细节中提炼而非鸡汤?
- [ ] 悲伤处是否克制?骄傲处是否不炫耀?
- [ ] 情绪价值是否拉满——读完是否有"回忆满满、感动常在"的感觉?
- [ ] 工作相关叙事是否突出团队价值而非个人英雄主义?
- [ ] 家庭相关叙事是否涵盖所有家庭成员(伴侣、孩子、父母)?
- [ ] 叙事是否贴合中国文化——含蓄内敛、重关系重感恩、无西式鸡汤/成功学话术?
- [ ] 成就表达是否归功于团队/家庭/经历而非个人?
- [ ] 配色是否为微信风格(主色 #07C160、白底深灰字、浅灰卡片)?
- [ ] 是否生成了足迹打点地图(地点≥3个时必须有)?
- [ ] 字号在手机端是否清晰可读(默认 DPR=2,宽度 2160px)?
- [ ] 是否采用分片截图 + 无损拼接导出(而非超长 fullPage 一次性截图)?
- [ ] 总高度是否在合理范围(默认建议 3500~8000px,超长场景已正确分片导出)?
- [ ] 署名是否为 loap's claw?
- [ ] 尾声最后一句是否留有温暖余韵?
- [ ] 是否同时交付了 HTML + PNG 长图两个文件?
小红书图文
- [ ] 每张图是否 1080×1440px(DPR=2 输出 2160×2880px)?
- [ ] 封面页是否有钩子标题让人想看下去?
- [ ] 每张内容页是否视觉撑满,无大面积空白?
- [ ] 尾声页是否呼应全文,留有温暖余韵?
- [ ] 是否为每张图生成了对应文案(标题+正文+标签)?
- [ ] 文案标题是否口语化、有钩子?
- [ ] 文案正文是否 200字以内,适合手机阅读?
- [ ] 标签是否覆盖 5-8个主题词?
- [ ] 配色是否沿用微信风格?
- [ ] 是否附上发布建议(发布时间、互动引导)?
示例:主题提炼思路
案例 A:技术人 + 旅行爱好者 + 奶爸
壹 · 山河篇 — 走过的山河都变成了身上的光
贰 · 柔软篇 — 写代码的手,也会给儿子叠千纸鹤
叁 · 热爱篇 — 心里那团火,从未熄灭
肆 · 有趣篇 — 正经了一天,朋友圈里放飞自我
案例 B:美食博主 + 摄影爱好者
壹 · 味蕾篇 — 每一口都是认真的
贰 · 光影篇 — 镜头里的世界比现实更温柔
叁 · 漫步篇 — 不赶路的时候,路自己会开花
肆 · 深夜篇 — 凌晨的感悟最诚实
案例 C:创业者 + 家庭至上
壹 · 战场篇 — 白天披铠甲
贰 · 港湾篇 — 晚上卸盔甲
叁 · 信念篇 — 做难而正确的事
肆 · 偷闲篇 — 忙里偷来的半日闲
注意:以上仅为示例,实际主题必须从素材分析中产生,不可直接套用。
注意事项
- 一个人的回忆录 ≠ 多人日报。语气要贴近这个人,像在写信给 TA
- 广告内容一律跳过,不收录进回忆录
- 转发内容:如果附带了有价值的个人评论,可以收录;纯转发忽略
- 情绪最重的一条(如亲人离世)要单独处理,文字要克制、有分量
- 足迹地图默认生成:在识别内容时就要主动提取所有地点信息。仅当独立城市少于 3 个时,才可跳过足迹地图板块
- HTML + PNG 长图都是最终交付物。PNG 长图是用户拿去发朋友圈的,HTML 是预览和二次编辑用的。确保 PNG 在手机上清晰可读
- 配色固定为微信风格(见核心原则第3条),不随人物气质或内容基调改变。因为最终是在朋友圈发表,微信风格最贴合
- 避免个人英雄主义,贴合中国文化(见核心原则第4条)。成就叙事归团队/家庭/经历,表达含蓄内敛、重关系重感恩,杜绝西式鸡汤和成功学话术
- 长图导出默认走分片拼接:先拍平动态状态,再按纵向切片截图并无损拼接;除非用户明确要求,不要优先使用超长
DPR=3 + fullPage一次性截图 - 小红书图文是附加交付物:在朋友圈长图完成后生成,每张图内容必须撑满,文案必须配套
Scan to join WeChat group