用 motion 制作影片
motion 是一种用于旁白和解说视频的视觉风格,以文字形式记录:影片的外观(背景、色彩、字体)和动效(元素如何出现、变化和消失)。它不包含影片内容:没有故事、脚本、场景或时间线。你提供故事;motion 决定其外观和动效。其格式为 SPEC.md(motion/0.5)。一个 motion 由其 ID、创建者的 GitHub 名称和 slug 命名:例如 @iamsuosi/lab-notebook。在 motionhub 上每个 ID 都包含这两部分。
一个 motion 是一个目录:
| 文件 | 从中获取的内容 |
|---|---|
motion.json | 其沙盒(scope)和 slug(合称 ID)、版本、名称、一句话描述、作者和许可证;lang 是 MOTION.md 的语言;fit 说明其适用场景 |
MOTION.md | 用文字描述的视觉风格。始终包含五个部分:本质、色彩、字体、动效、避免。格式定义:https://github.com/motionhub-dev/motions/blob/main/SPEC.md#5-motionmd |
tokens.json | 精确的值,作为 W3C 设计令牌:color、font,通常还有 duration 和 cubicBezier |
poster.jpg | 使用该 motion 制作的影片中的一帧 |
CREDITS.md | 所需的所有字体和资源,包括其许可证和来源 |
react/ | 该 motion 的组件,适用于任何 React 引擎(第 5 节):parts/,它们在 assets/ 中导入的文件,以及每个组件的预览图片位于 previews/ |
<tool>/ | 为另一种工具准备的现成模块。忽略未使用的工具目录 |
一个 motion 也可以是一个文件:一个以包含 spec、name 和 tokens 的前言开头的 MOTION.md,采用简短形式(例如 floor: "#E8D5B7")。它表示与 tokens.json 相同的内容,但没有组件、海报或致谢。
1. 选择 motion
- 用户指定了名称(一个名称、ID 或
motionhub.dev/m/<id>链接):使用它。 - 项目中已有 motion:项目根目录下的
MOTION.md,或motion/MOTION.md:使用它,然后转到第 3 节。一个项目可能在motions/中包含多个 motion:从 motionhub 复制的位于motions/@<scope>/<slug>/,项目自己的位于motions/<name>/。使用每个场景计划中使用的那个;如果计划没有说明,请询问。项目也可能包含其他设计文件,例如frame.md或design.md。motion 决定影片的外观和动效;遵循其他文件来处理 motion 未说明的内容,并告知用户它们之间存在不一致的地方。 - 否则进行搜索:
npx @motionhub/cli search <words>(无参数时列出所有 motion),或阅读索引https://motionhub.dev/api/motions.json,其行包含slug(ID)、name、line、fit、catalogs、tags、lang、poster和package,路径相对于https://motionhub.dev。从影片的形式开始:catalogs列出 motion 所属的分类(explainers、data、stories、tutorials、breakdowns和footage,用于在用户提供的视频上绘制,因此仅当用户有视频时才提供此选项;https://motionhub.dev/api/catalogs.json列出所有分类)。然后根据fit匹配主题和媒介,fit.for说明其适用场景,fit.not说明其不擅长的场景。为影片主题设计的 motion 比通用的 motion 更合适。提供两到三个 motion 及其海报,让用户选择。仅当用户要求时才自行决定。
2. 获取 motion
将整个 motion 复制到项目中,以使影片保持创建时使用的版本:
npx @motionhub/cli get <id> # 复制到 ./motions/<id>/,根据索引的 SHA-256 校验,记录在 motions.lock.json 中
npx @motionhub/cli get # 获取 motions.lock.json 中记录的所有 motion(当项目有此文件且 motion 缺失时)
一部影片可能使用多个 motion,每个部分或每种场景类型一个:逐个获取,它们并存于 ./motions/ 中。切勿修改 ./motions/@<scope>/ 中的副本:如需适配,将其复制到 ./motions/<name>/ 并在那里修改。
如果没有 Node:从 https://motionhub.dev/m/<id>/<version>.tgz 下载,根据该行的 package.sha256 校验,然后解压。如果没有 shell:逐个获取 https://motionhub.dev/m/<id>/MOTION.md、tokens.json、motion.json 和 CREDITS.md。
3. 完整阅读
在绘制任何内容之前,完整阅读 MOTION.md,并同时阅读 tokens.json,或前言中的 tokens。如果有匹配你工作语言的 MOTION.<lang>.md,你可以阅读它;但它不会包含 MOTION.md 中没有的内容。
4. 制作影片
- 值是精确的。 每种颜色、字体、时长和缓动函数都来自 motion 的令牌,按名称使用,并转换为引擎的术语。字体令牌是一个字体栈:按顺序使用其字体。切勿目测近似颜色。
- 本质决定每一帧。 每一帧必须具有它命名的特征,并且不得偏离它所说的 motion 不包含的内容。
- 色彩和字体是角色,而非调色板。 每个令牌仅用于其章节所述的目的;未说明颜色的内容保持无色。
- 动效是时间控制。 元素按照所述的方式出现、变化和消失,并且按照所述的方式与旁白或音乐同步。未说明移动的内容保持静止。
- 避免是强制性的。 完成之前,对照“避免”下的每一点检查影片。
- 切勿编造数字。 影片中的每个数字、日期和数量都来自用户的故事或他们提供的来源。如果缺少某个数字,请留下可见的占位符并告知用户。
- 故事是你的。 根据影片的内容布置每个场景。不要复制海报或任何示例的主题、文字或布局。
- 组件是捷径。 如果 motion 有
react/或你正在使用的工具的目录,请使用其组件(第 5 节)。文字和令牌仍然具有约束力。
5. 在你的引擎中
当 motion 包含 react/ 时,使用其组件而不是重新绘制外观。它们是仅导入 @motionhub/runtime 的 React 组件,绑定程序为你的引擎提供时间和令牌:
| 引擎 | 绑定 | 使用方法 |
|---|---|---|
| Remotion | npm i @motionhub/remotion | 将组合包装在 <MotionProvider tokens={tokens}> 中(import tokens from '../motions/<id>/tokens.json'),添加 <MotionFonts />,并从 ../motions/<id>/react/parts/<file>.tsx 导入组件。在使用多个 motion 时,将每个场景包装在来自 @motionhub/runtime 的 <MotionScope tokens> 中 |
| HyperFrames | npm i @motionhub/hyperframes,然后 npx motionhub-hyperframes --out assets/motion(针对 ./motions/ 中的每个 motion) | 加载 assets/motion/motion.css 和 motion.js;Motion.mount(el, (t) => [...]) 从你的 GSAP 时间线中绘制 Motion.components。在使用多个 motion 时,分别为 Motions[<id>] |
首先阅读绑定的 README。每个组件的 meta 说明其用途(purpose、line、fits)以及每个参数的含义,react/previews/<file>.jpg 显示其外观;仅在使用时阅读组件的代码。类型为 progress 的参数从 0 到 1:在你的引擎中根据调用它的文字对其进行动画处理。在 3D 中绘制的组件会导入 three,你需要安装它。@motionhub/runtime 中的 Caption 以 motion 的字幕皮肤绘制一句口头台词。根据你的故事布置每个场景;组件提供外观,而非影片本身。
否则,或者对于组件未绘制的部分:令牌是 DTCG 值,npx @motionhub/cli tokens --out tokens.json 从单个文件中的 motion 输出这些值,用于绑定或主题;在每个引擎中只进行一次转换(一个主题模块),并在各处按名称使用:
- 颜色:
$value.hex。 - 字体:
$value是一个栈:CSSfont-family依次是其名称,每个加引号,通用字体族放在最后。 - 时长:
$value是{value, unit},单位是s或ms。以帧计数的引擎将秒乘以帧率并四舍五入。 - 缓动(
cubicBezier):$value是[x1, y1, x2, y2],与 CSScubic-bezier(x1, y1, x2, y2)曲线相同。不支持此曲线的引擎则进行采样。
| 引擎 | 主题 | 时间控制 |
|---|---|---|
| Remotion | 使用 @motionhub/remotion 中的 useMotion();否则创建一个 theme.ts 导出颜色和字体栈。在第一帧之前使用 @remotion/google-fonts 或 @remotion/fonts 加载字体 | const {fps} = useVideoConfig();时长是 Math.round(seconds * fps) 帧;interpolate(frame, [start, start + frames], [0, 1], {easing: Easing.bezier(x1, y1, x2, y2), extrapolateLeft: 'clamp', extrapolateRight: 'clamp'})。优先使用 interpolate 配合 motion 的曲线,而不是 spring(),因为 motion 不需要它的过冲 |
| HTML 和 CSS | 在 :root 上设置自定义属性(--color-ink: #1B2A47) | 使用 transition 或 animation,配合时长和 cubic-bezier(...);Web Animations API 接受相同的 easing 字符串 |
| GSAP | 相同的自定义属性 | 时长以秒为单位;通过 CustomEase.create('arrive', 'M0,0 C x1,y1 x2,y2 1,1') 传递曲线 |
如果 motion 也有适用于你引擎的目录(remotion/),其中的模块是对组件的补充:首先阅读其 README。
6. 字体与致谢
- 安装
CREDITS.md中命名的字体,从其来源获取并遵守其许可证。如果某个字体不可用,请使用同一角色中最接近的开放字体,并告知用户。 CREDITS.md中命名的资产在遵守其许可证和要求的致谢的情况下使用。license.text涵盖 motion 的文字、令牌和图片;CC-BY-4.0和CC-BY-SA-4.0要求注明来源。在影片的描述或片尾字幕中添加一行类似这样的文字:Look: Ink Scroll by SuoSi, motionhub.dev/m/@iamsuosi/ink-scroll, CC BY 4.0.license.code涵盖工具目录中的代码。
7. 修改 motion 以及分享自己的风格
可以自由地为一部影片改编一个 motion,在你的副本中(./motions/<name>/)。修改后的副本不再是该版本:不要以相同的 ID 和版本发布。
要发布用户制作的风格(仅当用户要求时):
npx @motionhub/cli init <slug> --github <他们的 GitHub 登录名>会创建./motions/<slug>/,其中包含所有需要填写的必需文件,作为 motion@<他们的登录名>/<slug>(询问他们的登录名;如果已登录 gh,可以省略--github)。- 从他们的项目中获取风格,而不是影片:主题的颜色和字体放入
tokens.json(包含项目使用的时长和曲线);MOTION.md包含五个部分,说明此风格下所有影片的共同特征,但绝不包含此影片的故事;CREDITS.md列出每个字体和资产及其许可证;motion.json中的fit要如实填写:仅当该风格能容纳三个不相关的主题时才设为general,否则设为topic并指定其针对的主题,或者如果它在用户自己的素材上绘制则设为overlay。 poster.jpg:他们的影片中的一帧,JPEG 格式,宽度 960 到 3840 像素,最大 500 KB(Remotion:npx remotion still <composition> poster.jpg --frame=<n> --image-format=jpeg)。- 可选地,创建可复用的组件,放在
react/parts/中,如 CONTRIBUTING.md 所述:仅导入react和@motionhub/runtime的 React 组件(在 Remotion 中,使用其中的useTime()和useVideoConfig()而非 Remotion 的),将变化的部分作为 props 传入,并且不包含此影片的故事。 - 获得他们的同意后,
npx @motionhub/cli share motions/<slug> --wait运行其拉取请求将运行的检查,并将风格上传到 motionhub.dev。无需 git、gh 或 GitHub 令牌。将链接和它打印的代码原样提供给用户。他们打开链接,使用 GitHub 登录,检查 motion,输入代码并认证 DCO,然后 motionhub 以他们的名义打开拉取请求。该命令随后打印拉取请求的地址:也将其提供给他们。切勿代表他们输入代码或提交。如果他们更愿意使用自己的 gh 分支,npx @motionhub/cli share motions/<slug> --pr可以做到。
单个文件的 motion 从步骤 1 开始以相同的方式发布。然后 npx @motionhub/cli tokens --out motions/<slug>/tokens.json 写入其值,其 name 和 lang 放入 motion.json,其正文放入 motions/<slug>/MOTION.md,不包含前言。motion.json 的其余部分、CREDITS.md 和 poster.jpg 按如下方式填写。
要发布用户已发布的 motion 的新版本(仅在用户要求时,例如“从此项目发布 @/ 的新版本”):
- 准备 motion:他们在
./motions/<name>/中的副本,或者npx @motionhub/cli get @<scope>/<slug>并将./motions/@<scope>/<slug>/复制到./motions/<slug>/以便在其中修改。 - 根据他们的项目进行所需的更改,并遵守
MOTION.md所述的外观;全新的风格应创建新的 motion。 - 将
motion.json中的version提升到已发布版本之上:修复问题使用补丁号,添加内容(组件、章节)使用次版本号,更改会影响已有影片的外观则使用主版本号。已发布的版本永不更改。 - 如上所述执行
npx @motionhub/cli share <dir> --wait:他们打开链接并提交;如果他们的拉取请求已经打开,新版本会添加到该请求中。只有 motion 的作者之一可以更改它;其他作者的分享会打开自己的拉取请求。--wait最多等待 30 分钟。
要在审查拉取请求的评论后修改 motion,阅读评论(https://api.github.com/repos/motionhub-dev/motions/issues/<n>/comments 和 .../pulls/<n>/comments,无需令牌),根据要求进行修改,然后以相同方式再次分享。
要基于他人的 motion 构建,请以你自己的沙盒发布,在 motion.json 的 basedOn 中注明其名称([{"id": "@iamsuosi/lab-notebook", "version": "1.0.2"}]),并在 CREDITS.md 中说明你使用了什么以及修改了什么;只有原作者才能修改原始 motion。
8. 交付前检查
如果 motion 有海报,请将你的影片的一帧与 poster.jpg 并排放置:相同的地面,相同颜色扮演相同角色,相同的字体。然后再次对照影片阅读“本质”和“避免”,并修复不符合的地方。