全部文章

草稿不是一个文件,而是一张标识符关系图

用检查点、内容寻址素材和版本化文档设计云草稿,让崩溃恢复、跨设备续编、冲突与配额都有明确语义。

用户想带走的是时间线,而不只是字节

需求是:在手机上剪到一半,换一台设备继续。云备份主要保存字节,云草稿则要保存含义——不同设备、平台和编辑器版本,打开后仍然理解轨道、裁剪、关键帧、特效与文字。

第一步是拆开两种东西:项目文档是几百 KB 的结构化数据,素材则可能有数 GB。把它们打成一个 zip,会让修改字幕也重新上传整套素材,去重、续传和快速打开都变得困难。

云草稿的文档与素材结构小型文档用内容哈希引用素材,素材存储提供原片、代理与缩略图等表示。

云端同步的对象,应是一张带版本的引用关系图。

本地可靠性:不要等崩溃时才保存

崩溃处理器运行在可能已损坏的环境里,不适合序列化整个项目;内存终止和 watchdog 也可能不给回调。保护必须放在崩溃之前,以及下次启动之后。

每次编辑向追加日志写入带校验的小记录;定期将完整快照写到临时文件,再原子替换一个代际槽位;会话开启时创建 dirty 标记,正常结束才删除。进入后台时,在有限后台任务时间内提交会话。

恢复使用最后完整快照加上其后的有效日志,遇到校验失败记录停止并截断尾部。实际可恢复范围取决于写入与落盘策略,不能把“调用了写入”视为绝对不丢最后一次操作。

恢复还需要失败计数。若草稿数据本身触发崩溃,反复自动恢复会形成循环;连续失败后应隔离数据,提供安全入口。

这些机制导出一个关键概念:Checkpoint(检查点) 是完整、一致、由正常保存或用户确认恢复得到的版本。日志、滚动快照与未确认恢复数据属于本机工作状态。

只同步检查点

产品目标是跨设备接续,而不是多人同时剪辑。时间线的并发裁剪不容易像文本那样自动合并;猜测用户意图可能得到结构合法、视觉却错误的结果。

从本地编辑到云端可见的检查点流程本地提交后预检配额,先上传缺失素材,再切换版本指针;分叉生成冲突副本,超额进入待同步。

每次上传声明基于哪个云版本。服务端发现基准已经变化,就生成标注来源的冲突副本,而不覆盖对方。用户选择保留哪份,系统不静默丢弃编辑。

未确认的崩溃恢复状态不能自动上传,避免一个设备的异常会话传播到其他设备。

素材层:按内容命名

同一素材在多个草稿中使用,内容哈希相同,存储层可以只保存一次。上传检查点时对比 manifest,只传缺失 blob,并支持恢复传输。

设备上的 PHAsset.localIdentifier 不能直接当作跨设备身份。导入时解析素材字节、生成内容地址,草稿从此使用稳定引用。若用户已删除尚未上传的原素材,应在本地边界报告缺失,而不是等另一台设备出现无法解释的错误。

素材还需要多个表示:导出用原片,编辑用低码率代理,浏览用缩略图。新设备先获取文档与代理,不必等待全部原片;需要导出时再准备完整素材。

可见性必须原子化:先使所需素材满足约定,再切换版本指针。这个指针切换才是云端提交。删除草稿则减少引用,素材通过带宽限期的垃圾回收清理,保留版本历史与恢复仍可能访问的数据。

Schema 升级要有明确规则

文档寿命长于写入它的客户端版本。每个文档携带 schema_version,每个客户端知道写入版本与最高可读版本,云端发布可接受的最低版本。

文档 Schema 的可读与可同步范围迁移在客户端向前执行,云端只存储版本化文档并检查最低要求。

低于云端最低要求时,先在本机执行升级链,再上传。每一步转换都有成对 fixture;依赖素材目录或默认值时,先提供明确、固定的输入,避免迁移结果随环境漂移。云端不承担编辑语义转换。

在客户端可读范围内,旧文档升级后正常编辑;比当前写入版本新、但仍受支持的文档进入兼容模式,未知节点原样保存、展示占位符,不擅自降低 schema 版本。超过可读上限则提示更新,避免在看不懂结构时继续编辑并损坏文档。

升级可能让旧应用无法再次打开本地草稿,因此“需要升级才能同步”应成为可见操作。用户暂不升级,就保留清晰标记的本地草稿,而不是悄悄让它看起来已经上云。

传输必须假设进程会消失

大素材通过文件支持的后台 URLSession 任务传输,启动时重新绑定 delegate,并根据系统未完成任务和持久记录恢复状态,而不是依赖内存。

大文件分片、分片重试与断点恢复可复用共享媒体传输层。草稿系统提供内容哈希作为身份,再由服务端幂等协议与在途去重避免重复接收;哈希本身并不会自动阻止并发重复上传。

网络错误使用退避与抖动重试;需要凭据刷新、配额处理或用户介入的错误进入有原因的等待状态。不能把每个失败都当成瞬时网络问题无限重试。

下载先取最小可用表示,所有上传、下载与 CDN 请求经过统一网络层,地区路由规则只落实一次。每个检查点追踪本地提交、预检、素材上传、指针切换、另一设备可见等阶段,测量成功率和同步耗时;没有崩溃不代表同步健康。

配额也是失败语义

传输前预检整个检查点的增量,最终提交仍需服务端一致性校验,避免并发变化绕过限制。若超额,检查点已安全保存在本地,但明确处于待同步状态;升级套餐或释放空间后再继续。

本地、上传中、已同步、待处理与冲突应逐草稿可见。不能让用户误以为尚未上传的工作已经在云端。

去重还会影响计费:同一 blob 被两个草稿引用,按存储一次收费还是按引用收费,要提前定义。否则“删了草稿却没释放空间”会成为无法解释的体验。

值得多投入的三个边界

首先是跨版本 Schema 演进:旧客户端不能在保存时剥掉未知节点。其次是渲染一致性:字体、色彩、特效和关键帧参数相同,不一定自动获得相同像素,需要跨平台验证。最后是检查点边界:不完整状态不能冒充完整版本跨设备传播。

从结构上看,文档像 commit,素材像内容寻址对象,上传与拉取像 push/pull,基准版本检查像 compare-and-swap,冲突副本像分支。引用关系开始随时间变化时,设计已经不只是文件传输,而是带历史、原子可见性和分叉规则的版本管理。