点一下屏幕上的数字宠物,它却像没听见。很多人第一反应是视频生成不行,但真正决定这一下“有没有被回应”的,是生成画面、动作调度、浏览器解码和缓存这一整条链路。

打开网易新闻 查看精彩图片

这是 Cariora 在做的事:给 AI 伴侣房间配上数字猫狗,把对话和预先拍好的视频反应拼在一起。这里只聊视频这一侧——一段段独立的片段,怎么变成人能上手互动的东西。

片段先要有“回去的地方”

一堆单看很好的片段,拼起来可能是一场灾难。前一段猫是前倾的,下一段开头它已经坐直了,单独看都没问题,切换的一瞬间猫像跳了一下。

普通房间反应的做法是共用一个关键帧:生成请求把同一张图同时作为起始帧和结束帧。房间锚点出发,到反应,再回到房间锚点;到瞥一眼,再回来;到休息,再回来。

这是对素材的约束,不是保证每一次生成都听话。管线会检查交付的帧,不合格的片段直接拒掉。同一场景内保持视频模型一致,也有助于避免反应之间出现质感和构图的变化。

换一个姿势就得另起一套锚点和真实过渡。比如站起来,需要一段从坐到站的片段、一个站立的休息循环,再加一条回去的路。把一张静态图往上挪,缺的正是身体动作本身。代价是新姿势要更多素材,也给调度器增加了必须理解的路径。

画面几乎不动,也可能是错误剪辑

早期切点逻辑犯过一个错:把“动作小”当成“可以切”。角色举着手几乎静止,从这一帧切到坐着的待机,姿势照样突变。

要回到房间锚点,有用的切点需要同时满足动作小和姿势接近锚点。其他过渡可以用经过审核的帧匹配,幅度更大的动作则必须停在允许的边界上。

播放环节还有另一种翻车方式。早期演示在动作之间用一张海报替换当前视频,海报和视频的宽高比略有差异,交接时裁切变了,看起来像背景在移动,尽管源片段共用同一个锚点。

播放器必须在下一个解码器准备好时保留当前画面。play() 的 resolve 并不等于新帧已经上屏。在支持的环境里,requestVideoFrameCallback 能提供与视频帧送进合成器绑定的回调。Cariora 在解码器交接时使用帧观测,准备失败时有带边界的恢复。但一段动作如果没有安全的提前退出点,可见的等待依然存在——素材本身决定了哪里能转。

先加载“回应”,再加载“花样”

早先的加载顺序是先待机、再几段表情、最后才是通用触摸反应。访客看到宠物在动,很自然会以为可以摸,而真正用来回应这一摸的片段还排在下载队列里。

现在的顺序把通用触摸反应紧跟在待机之后,再排其他早期有用的回应。进入不同房间有各自的顺序,因为入场素材必须赶在场景切换前到位。加载器限制并发数,也能优先某个被请求的片段;实测传输速度低时它会降低并发,免得后台下载跟正在等的回应抢带宽。

这里有三件不同的事要分别跟踪:房间可见、片段已加载、动作被允许。房间可见,并不能替任意一个动作证明后两件事。

如果请求的片段还在路上,一次点击会得到确认和一段有边界的等待;已加载且规则允许的触摸片段可以先顶上;等待超时,房间会说明它还在准备。没有对应素材的动作就是不可用,控件和说明都必须反映这个状态。角色家族同理:人类伴侣不该因为某个共享组件最早是给狗写的,就继承狗的游戏控件和音效库。

预热播放器真正会读的那个资源

预加载只有在播放能复用结果时才有意义。Cariora 把播放器媒体统一走一个同源 URL 辅助函数,包括进房间之前展示的媒体。

对一个视频对象,辅助函数把对象键转成播放器路由:对象键 uploads/cariora/ab/…mp4,对应播放器 URL /api/pet-assets/uploads/cariora/ab/…/mp4。末尾多出的扩展名段,是为了绕开一个本地中间件问题——以 .mp4 结尾的路径会在到达处理器之前被当成静态文件。

预热用的是和房间相同的普通 GET,并消费响应体。房间加载器取回片段字节,把 blob URL 交给解码器,这样解码器切换时可以复用本地片段。

共享 URL 不等于所有媒体都公开。边缘 worker 会检查一份公开官方目录素材的显式索引,这些可以走共享 CDN 缓存;其他键交给应用 worker 做所有者鉴权,并使用浏览器私有缓存。内容哈希标识的是不可变的字节,不是读取这些字节的权限——对用上传照片定制的伴侣来说,这个区别尤其重要。公开路径还保留了浏览器视频请求需要的字节范围行为。

用冷缓存测第一次点击

一个有用的浏览器检查从空缓存和限速网络开始:走真实的领养或伴侣列表流程进入,等第一个待机画面出现,然后在剩余片段还没下完时点下去。

要测的是到“回应帧真正呈现”的间隔,同时记录确认提示有没有出现、播的是不是正确反应、有没有问候或背景动作把这次请求挤掉。

这些检查抓到过模块测试漏掉的 bug。一个用了零值初始播放时间戳,导致从未播放过的反应在进房间后立刻显示为冷却中;另一个让陆续到达的问候素材替换了待处理的触摸请求。两者都会产生同一句抱怨:“我点了,什么都没发生。”改视频提示词,两个都修不好。

当前方案有边界:长动作可能要播完才能接下一个;说话用的是预制动作,不是任意音素的精确口型动画;素材稀疏限制了伴侣能展示的不同反应数量。更好的调度能让已有素材用得更充分,但补一个缺失的动作,仍然要拍、要审。

想先看基本交互,Cariora 的公开宠物演示提供了一小组预制反应,不用登录。做类似项目,这个小闭环就够当第一版:一个锚点、一个待机、一个触摸回应,再加一次冷缓存下的首次点击测试。