首页 / 全部技能 / 内容创作 / text-message-animation
内容创作 · iart-ai/text-message-video-skills

text-message-animation

This skill should be used when the user asks to "make a fake text message video", "animate an iMessage conversation", "create a text story video", "do a chat reply animation", "WhatsApp/SMS conversation video", "typing indicator animation", "render a chat thread to a video", or "batch text-message videos from a script/CSV". Covers sent/received bubble layout, staggered appear timing with typing indicators, read receipts/timestamps, per-message pop sound-sync, 9:16 safe-area, and data-driven render from a messages array.

L4 高权限 · 分级授权与审计V1 已固定执行命令联网读写文件Dual-pass Audit
Author iart-aiGitHub iart-ai/text-message-video-skills ↗Stars 4License MIT(仓库根 LICENSE 为 "MIT License / Copyright (c) 2026 iart.ai";GitHub API spdx_id = MIT;.claude-plugin/plugin.json 亦声明 "license": "MIT")Commit 3a800e1e9b
管控等级描述 skill 的能力与建议配套的管控措施,不代表质量或安全认证,也不表示可用或不可用。是否使用由用户和管理者决定。不同 agent 宿主对权限的约束各不相同,请勿假定宿主一定会提供安全兜底。第三方 skill 版权归原作者,使用风险由使用者自行承担。

1实现原理 · 为什么它能做到

第一条不可谈判规则:一次只揭示一条消息、并且有节奏——先打字、再弹泡、再留阅读间隙,绝不第 0 帧倾倒整段对话。

skills/text-message-animation/SKILL.md
1. **One message reveals at a time, on a rhythm.** The retention comes from the drip: a beat of typing, then a bubble pops in, then a pause to read. Never dump the whole thread at frame 0 — pace it like a real conversation (a typing indicator before received replies, a short read-gap after each bubble).
这里在做什么:把这个品类的留存来源说成「滴灌」而非剧情——于是节奏参数(typingMs/delayMs)成为一等公民,而不是装饰。

第二条不可谈判规则:chrome 必须在半秒内被认出是哪个 app(颜色/气泡/尾巴/回执/头部全对齐),不许混搭。

skills/text-message-animation/SKILL.md
If a viewer can't tell which app it is in the first half-second, the illusion breaks.
这里在做什么:把「像不像」转成可验收的清单(iMessage 蓝 / SMS 绿 / WhatsApp 深绿 + 双勾),并给出完整调色板表;混搭(iMessage 泡 + WhatsApp 勾)被明确禁止。

数据模型优先:整个视频由一条 Message[] 驱动,剧情写成数据,渲染器只负责播放。

skills/text-message-animation/SKILL.md
Everything is one array of messages. Author the story as data; the renderer just plays it.
这里在做什么:这是「可批量」的根因——一条模板 × N 份脚本=N 条视频;CSV 的列(from,text,typingMs,delayMs,status)被设计成能直接映射。

时间线由数组游标推导:走一遍消息累加 cursor,产出 typingStartMs / typingLenMs / enterMs,所有弹簧、音效、滚动都读它。

skills/text-message-animation/SKILL.md
const durationMs = cursor + 1000; // tail pad so the last bubble is readable
这里在做什么:把「每条消息什么时候出现」变成一次确定性推导,从而消灭手工摆帧——也是时长可自动计算的前提。

时长交给 calculateMetadata 从游标算,禁止手写帧数。

skills/text-message-animation/SKILL.md
Compute `durationInFrames` from `durationMs` in `calculateMetadata` so a longer script makes a longer video automatically.
这里在做什么:解决「脚本一长,视频就截断/留白」这类批量生产的典型事故;每个 thread 各自算出自己的长度。

打字指示器只出现在收到的消息前,且用正弦呼吸、帧驱动(不用 CSS 动画计时器)。

skills/text-message-animation/SKILL.md
Only received messages type; sent messages just pop (you don't watch yourself type).
这里在做什么:把「像真的」拆成角色规则(自己不会看自己打字),并保证 headless 渲染下指示器仍在动(帧驱动而非计时器)。

自动滚动用弹簧逼近目标位移,让最新气泡落在视野下三分之一,而不是跳变。

skills/text-message-animation/SKILL.md
Animate the scroll offset toward the target with a spring each time a message lands — it should glide, not jump.
这里在做什么:线程长过可视区后,「看不看得见最新消息」决定观感;弹簧位移既解决可见性又保留手机的物理感。

每条消息排一个音效(发/收不同),且必须排进帧时间线而非事件回调。

skills/text-message-animation/SKILL.md
Never trigger sound off a timer — schedule it on the frame timeline so it survives headless render.
这里在做什么:把「真实感」的一半交给声音,同时说明为什么不能用事件驱动——渲染器没有实时时钟。reference 另给了每条 <300ms 与键盘底噪的调法。

竖屏安全区按四段留白定义(顶部状态栏 ~120px、头部 ~150px、底部输入+平台 UI ~360px、侧边留 gutter)。

skills/text-message-animation/SKILL.md
| Bottom input + UI | ~360px | Fake compose bar AND the platform's caption/CTA/audio UI both crowd the bottom |
这里在做什么:本 skill 的底部禁区(360px)比同仓短视频类(320px)更大,因为要同时让出「假输入框」与平台 UI;气泡永不贴边是「这是手机」的视觉来源。

验证回路:先出打字帧/中段帧/末帧三张静帧,判据包括「打字帧左侧只有三点、没有真气泡」与「最新气泡没被输入框遮住」。

skills/text-message-animation/SKILL.md
At a typing frame the indicator (not the bubble) shows on the received side; the bubble pops only after.
这里在做什么:把「节奏」这种抽象要求变成可判定的帧级检查;reference 另给同布局的单文件 HTML 预览 + `?t=N` seek harness,对应仓库的 seek-shot.sh。

2核心能力

01三种 app chrome 与调色板(iMessage 蓝 / SMS 绿 / WhatsApp 深绿 + 双勾),含头部栏与状态栏
02气泡与尾巴规则:max-width 药丸、只给连续同一发送者最后一条加尖角
03弹簧气泡入场 + 三点打字指示器(正弦呼吸、帧驱动)
04回执 / 时间戳分隔 / tapback 反应(锚到各自气泡的 enterMs,而非全局帧)
05自动滚动(弹簧逼近目标位移,最新气泡落在下三分之一)
06每条消息一个音效(send/receive),按 enterMs 排进帧时间线;可选键盘底噪床
07数据驱动批产:JSON/CSV 线程 → Message[] → 一次 bundle 渲染 N 条(@remotion/renderer)
08轻量预览路径:同布局的单文件 HTML + `?t=N` seek harness(对应仓库 scripts/seek-shot.sh)

3外部依赖

KindDependency / Endpoint
clinpx remotion still / render / compositions
package@remotion/bundler + @remotion/renderer(批产路线:bundle 一次、renderMedia 多次)
cliscripts/contact-sheet.sh + scripts/probe-mp4.sh(仓库根共享验证工具箱,SKILL.md 明列)
cliscripts/seek-shot.sh(Light tier:驱动单文件 HTML 的 `?t=N` harness 截图)
network(可选,reference 建议)Remotion Lambda 并行渲染上百条片

4管控建议与判定依据

建议配套管控措施
面向 Agent
分级或逐次授权,建议在沙箱运行
面向管理者
审批流程、可回滚、全程审计
判定依据(文件路径与关键语句摘要)
  • scripts/: 执行本地脚本或命令: (SKILL.md 明列的验证回路)`npx remotion still TextThread out/f-{typing,mid,end}.png
  • 网络端点: 声明外部网络访问: `npx remotion …` 与批产段的 `@remotion/bundler`/`@remotion/renderer`:首次经 npm 官方渠
  • 本地工作目录: 文件读写与工件输出: agent 按本 skill 构建的 Remotion 工程与 out/thread.mp4(或批产时的 out/chat-001.mp4 … out
审计说明: 。三段自证:① 判级对象=skills/text-message-animation/(find 确认只有 SKILL.md、references/{bubble-recipes.md,data-driven.md}、README.md 三个 .md 加一个 0 字节 README,零脚本、零资产);② 目录内自身行为=本地写入(Remotion 工程、out/*.mp4、静帧、chat.html 预览)+本地 CLI(`npx remotion`;ffmpeg/ffprobe 与 playwright 截图均经仓库根 scripts/),skills/ 全域 `process.env` / `api[_-]?key` / `token` / `cookie` / `https?://` 均 0 命中;③ 唯一网络面是 npm 官方渠道取包(remotion / @remotion/* 及 seek-shot 的 playwright),与站内蓝档先例(hyperframes、general-video、motion-background)同口径;reference 建议的 Remotion Lambda 属用户自备云账号的可选扩容路径,非 skill 默认行为,亦不读 skill 侧的凭据。不升黄/橙:无固定公开端点查询、无抓取、零凭据/环境变量读取、零素材外发(音频与头像是本地文件,不进任何第三方服务)。非红档:无 TLS 降级、无沙箱关闭、无反自动化绕过、无任意代码执行面。需另记(不改档)者见 injection_surface 与 verdict.risks:外部数据(CSV/LLM 产出)直接进屏上文案,zod 只校验结构不校验内容;伪造聊天界面用于「fake text」题材本身还有平台政策与伦理面(本报告只做技术侦查,不评价用途)。

5第二遍独立确认

  • [ok] 「一次一条 + 打字只出现在收到的消息」是否真在代码里成立(防第一遍只读散文) — reference §5/§9 的组件把每条消息包在 `<Sequence from={f(m.typingStartMs)}>` 内,仅当 `m.typingLenMs > 0`(由 `m.from === "them" ? (m.typingMs ?? 800) : 0` 决定)才渲染 `<Typing />`,随后 `<Sequence from={f(m.enterMs - m.typingStartMs)}>` 弹泡;SKILL.md 也明写 "Only received messages type; sent messages just pop"。声明与实现一致。
  • [ok] 数据驱动时长(calculateMetadata)是否真能自动出正确长度 — SKILL.md 给 `durationMs = cursor + 1000` 并写 `Compute durationInFrames from durationMs in calculateMetadata`;reference §9 的 Composition 把 `durationInFrames={300}` 标为默认值并由 `calculateMetadata` 覆盖为 `Math.ceil((durationMs / 1000) * 30)`,§4 再次强调 "never hand-set the duration"。三处自洽。
  • [discrepancy] reference 示例 import 的模块是否随包分发(第一遍未察觉) — data-driven.md §5 的批渲染脚本写着 `import { csvToThreads } from "./csvToThreads";`,但仓库内并不存在 csvToThreads 文件(全仓仅 .md 与 .sh/.git)。属示意代码:照抄会直接报模块不存在,读者需按 §3 的 CSV 列约定自写映射。同型问题在 CSV 示例里也可见(示例行 `2,Alex,me,no,,400,read` 省略了线程首行)。对 pin commit 有效的真实出入,非虚假能力声明。
  • [discrepancy] 音效能力落地是否需要用户自备资产 — SKILL.md 与 reference §8 都用 `staticFile(m.from === "me" ? "send.mp3" : "receive.mp3")`,但仓库内不含任何 mp3;data-driven.md 只在 Tips 里提醒 "Keep `send.mp3` / `receive.mp3` / fonts in `public/`"。结论:音效同步是能力,但前置资产(发/收提示音、字体、头像)必须由用户提供——SKILL.md 的输出清单「One pop/ding per message」在缺资产时会静默退化。
  • [ok] 「轻量预览(`?t=N`)」与仓库 Light tier 脚本的契约是否真的对齐 — bubble-recipes.md §10 的 HTML 里实现了 `const t = new URLSearchParams(location.search).get("t"); if (t !== null) { tl.pause(); tl.seek(parseFloat(t)); }`,与 scripts/README.md 描述的 seek-shot.sh 契约(页面 load 时 `tl.pause(); tl.seek(t)`)逐字对应。三包中只有本 skill 真能用上 seek-shot.sh。
  • [unlocatable] 「one of the highest-retention faceless short-form formats」是否有据 — SKILL.md 开头断言本格式为最高留存的 faceless 形式之一,仓库内无数据、无引用、无来源标注;本次为只读侦查,不验证该断言,仅记为文档声明。
  • [discrepancy] 包间一致性:同为 2026-06-22 发布的三个 iart 包,skill 目录结构是否统一 — tiktok 包四个 skill 各带人读 README(1377–1494 字节);本仓库的 text-message-animation 与 youtube 包的两个 skill 的 README 均为 **0 字节**。功能不受影响(README 非 skill 加载所必需),但包间文档完整度不一致,属可核查的结构出入。

6结论

  • 把「像真的」拆成可核对的事实清单:颜色/尾巴/回执/头部/状态栏/音效逐项定义,并禁止跨 app 混搭
  • 数据即内容:Message[] 单一契约 + JSON/CSV/LLM 三种作者路径,使「模板 × N 脚本」批产成为默认工作方式
  • 时间与时长全自动推导(游标 → enterMs → calculateMetadata),消灭手工摆帧这类批量事故
  • 节奏参数化:typingMs/delayMs 决定「悬疑」或「轻快」,同一模板能出两种手感
  • 三包中唯一双 tier 完备的 skill:Heavy(Remotion 出 MP4 + 批量)+ Light(单文件 HTML + `?t=N`,正好对应仓库 seek-shot.sh)
  • 验收前置且有判据:打字帧必须只有三点、最新气泡不得被输入框遮住、批量前先验一个代表线程
  • 适合: 适合:要做 chat-story / 假短信剧情类竖屏视频(TikTok/Reels/Shorts)的创作者与批量生产团队;尤其适合「一份模板 × 多份脚本/CSV」的工厂式产出,以及需要为每条对话单独对齐时长、音效、自动滚动的项目。也适合先用单文件 HTML 快速试排版、再上 Remotion 出片的流程。适合能接受「先验一个代表线程再批量」纪律的用户。
    不适合: 不适合:① 长对话/需要阅读回看的长内容(本格式靠节奏,逐条弹出不适合长文本);② 需要真实 app 截图或接入真实聊天数据的合规场景——这里是纯渲染的仿真界面,不接任何 IM 服务;③ 无音频资产又不打算准备提示音的团队(输出清单的音效项无法满足);④ 要求 100% 自动化质检的流水线(关键判据仍是人读静帧);⑤ 不接受「伪造聊天」题材相关伦理/平台风险的使用者。
    Install Agent-Ready
    ① Verified Mirror 2026-09-28
    Option A · Direct DownloadDownload text-message-animation.tar.gz
    sha256: fdd9560a3ce85697…
    Option B · Copy Guide for Agent
    install.json
    agent 读 JSON 指南后会自动从本站下载安装,无需更多说明。
    ② Upstream GitHub
    GitHub Repo ↗
    Pinned to commit 3a800e1e9b.