这篇能做出什么
照着做下来,你会拿到三样能直接演示的东西:
1. 一个实时互动会话。打开摄像头或共享屏幕,对着画面说一句指令,画面里的风格、光线或主体动作随之改变,中途不需要重新出片。
2. 一条"边播边改"的实时改视频工作流。手里已经有一段素材,不重剪,直接在它上面替换主体、换背景、改色调,其他部分保持不动。
3. 一段可探索的空间视频。把一段普通的单目视频变成带深度信息的 3D 场景,之后可以用环绕、推拉、小幅平移的视角去看它,而不是只能顺着原镜头走一遍。
三件事可以分开做,也能串成一条流水线:实时互动负责"下指令",实时改视频负责"改画面",空间视频负责"换视角"。做成之后,一个典型的交付物是——客户在浏览器里对着自己的产品视频说"换成日落光,背景换成水泥墙",几秒后看到结果,再点一下切到环绕视角看产品的侧面。
前置条件清单
动手前把这几项准备好,能省掉一半排错时间:
- 账号与调用权限:在 Vidu 控制台开通对应能力,拿到 API Key 或会话凭证。具体入口名称、额度与计费方式以官方页面为准。
- 浏览器:较新版本的 Chrome 或 Edge。实时链路依赖 WebRTC 与 MediaStream,老版本浏览器容易在获取摄像头时直接失败。
- 一个 HTTPS 地址或 localhost。浏览器只在安全上下文里允许调用摄像头和麦克风,纯 HTTP 的线上域名会被直接拦掉。
- 网络:实时链路对上行带宽和抖动敏感,建议先测一次上行。分辨率、帧率、并发路数都要按实际带宽留余量。
- 开发环境:Node.js LTS 或 Python 3.x 任一,以官方文档当前版本为准。只需要能起一个本地 HTTP 服务和发 HTTPS 请求。
- 素材:一段有明确主体、镜头运动平缓的视频(用于改视频和转空间视频),以及一张主体清晰的参考图。
- 一个可以反复用的提示词文件。实时场景下,临场想词是效率杀手。
分步骤
步骤一:先把三种能力的输入输出对齐
别急着写代码,先在白纸上写清楚这三行,后面所有配置都围绕它:
- 实时互动:输入是「视频流 + 文本指令」,输出是「改过的视频流」,考核指标是首帧响应时间和指令生效时间。
- 实时改视频:输入是「一段定长素材 + 编辑指令 + 可选的遮罩/参考图」,输出是「改后的素材」,考核指标是主体一致性和非编辑区域是否稳定。
- 空间视频:输入是「单目视频」,输出是「可换视角的场景」,考核指标是边缘是否干净、深度是否连续。
这三个的调参方向不一样:实时互动追延迟,实时改视频追一致性,空间视频追几何质量。混在一起调会互相打架。
步骤二:把凭证和地址丢进环境变量
不要在代码里硬编码密钥。用环境变量管起来:
```bash
export VIDU_API_KEY="你的密钥"
export VIDU_BASE_URL="官方文档给出的服务地址"
```
之后所有请求都从这两个变量拼出来。路径和参数名以官方文档当前版本为准,下面代码里的路径只作结构示意。
步骤三:打通实时会话
实时链路的骨架是固定的:先向服务端要一个会话凭证,再用这个凭证建立长连接,然后把本地摄像头流推进去,把返回的流渲染出来。
```javascript
// 1. 取本地摄像头
const local = await navigator.mediaDevices.getUserMedia({
video: { width: 1280, height: 720, frameRate: 30 },
audio: false
});
document.querySelector('#preview').srcObject = local;
// 2. 向服务端申请实时会话凭证
// 路径与字段以官方文档为准
const resp = await fetch(${import.meta.env.VITE_BASE_URL}/realtime/session, {
method: 'POST',
headers: {
'Authorization': Bearer ${import.meta.env.VITE_API_KEY},
'Content-Type': 'application/json'
},
body: JSON.stringify({
mode: 'interactive', // 或 edit / spatial,按能力切换
resolution: '720p', // 先降一档,跑通再往上加
fps: 24
})
});
const session = await resp.json();
// 3. 用返回的凭证建立连接,推流 + 收流
const pc = new RTCPeerConnection();
local.getTracks().forEach(t => pc.addTrack(t, local));
pc.ontrack = (e) => { document.querySelector('#output').srcObject = e.streams[0]; };
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 把 offer 和 session 凭证一起发给信令接口,拿回 answer
// 之后调用 pc.setRemoteDescription(answer),画面就会出现在 #output 上
```
跑通这一步的标志是:右侧预览窗口出现了经过处理的画面,哪怕还没加任何编辑指令。
步骤四:把"一句话指令"变成可复现的提示词模板
实时互动里最容易翻车的地方,是每次随口说的指令结构都不一样,导致效果忽好忽坏。解决办法是固定一个四段式模板:
```text
主体:<谁 / 什么东西,外观特征>
动作:<做了一件什么动作,幅度多大>
环境与光照:<在哪、什么时间、光源方向>
镜头与风格:<景别、机位运动、色调、质感>
```
一个填好的例子:
```text
主体:穿深灰风衣的中年男性,短发,左脸有一颗小痣
动作:缓慢转头看向左侧,幅度很小
环境与光照:雨夜便利店门口,霓虹灯牌在湿地面反光,主光来自右后方
镜头与风格:中近景,35mm 视角,轻微手持,写实,冷色调,细颗粒
```
实时场景下,只改其中一个字段,其他字段原样保留。这样画面不会因为整句话重写而整体跳变。
步骤五:做实时改视频,重点是"锁住不该动的地方"
改视频的常见需求有三类:换主体、换背景、改风格。它们对一致性的要求依次降低,做法也不同。
换主体:一定要给参考图,并且在指令里明确"保持其他人的位置、姿势、光照不变"。
```text
把画面中间的人替换为参考图中的角色,服装和发型与参考图一致;
保留原有姿势、动作节奏和周围环境;
不改变背景、不改变镜头运动、不改变其他人物。
```
换背景:先划出要替换的区域,再描述新背景。区域描述越具体,边缘越干净。
```text
仅替换人物轮廓之外、地平线以上的区域为黄昏城市天际线;
保留人物边缘、地面、阴影方向不变;
新背景的光源方向与原画面保持一致。
```
改风格:不动几何,只动色彩和质感,这类改动的稳定性通常更好。
```text
在保持所有物体位置、形状、运动轨迹完全不变的前提下,
将画面调为高对比黑白,胶片颗粒,轻微暗角。
```
要批量跑的话,用任务式接口更合适,一次提交一段素材和一个指令,异步拿结果:
```python
import os, time, requests
BASE = os.environ["VIDU_BASE_URL"]
HEAD = {"Authorization": f"Bearer {os.environ['VIDU_API_KEY']}"}
路径与字段以官方文档为准
task = requests.post(f"{BASE}/video/edit", headers=HEAD, json={
"video_url": "你的素材地址",
"prompt": "把主体替换为参考图中的角色,保留姿势与环境",
"ref_image_url": "你的参考图地址",
"keep_background": True
}).json()
task_id = task["id"]
while True:
r = requests.get(f"{BASE}/tasks/{task_id}", headers=HEAD).json()
if r["status"] in ("succeeded", "failed"):
print(r["status"], r.get("output"))
break
time.sleep(5)
```
步骤六:把单目视频转成可探索的空间视频
空间视频的关键不在提示词写得多花,而在源素材是否"好解算"。拍摄时注意三点:镜头平缓、主体和背景有明显前后景关系、避免大面积运动模糊。反光玻璃、纯色墙面、快速横摇是三类比较难处理的素材。
指令的写法重点在描述景深层次,而不是描述内容好不好看:
```text
为这段视频重建深度:前景是桌面和咖啡杯,中景是坐着的人,背景是窗户和街景;
保持三层的前后遮挡关系,玻璃上不要产生深度断裂;
输出可环绕视角,环绕范围控制在左右各 30 度以内。
```
生成之后,浏览方式通常是旋转视角、推拉距离、小幅平移。范围给小一点,超出重建范围的部分容易出现拉伸。把重建精度和视角范围分开调,先要几何稳,再要转得开。
步骤七:把三段串起来
一条可演示的流水线是这样跑的:
1. 用空间视频先给素材建立可换视角的场景,确认几何没问题。
2. 把其中一个视角的渲染结果,作为实时改视频的输入,改主体和风格。
3. 把实时互动的输出接到前端,让操作者用语音指令驱动第 2 步。
前端只暴露两个开关:一个是"指令生效"的按钮,一个是"切视角"的滑杆。中间的重连、队列、失败重试都藏在后面。
常见坑与排错
画面完全没反应。九成是浏览器权限或安全上下文问题。确认地址是 HTTPS 或 localhost,并在浏览器地址栏左侧检查摄像头权限是否放行。
延迟越来越高。多半是上行带宽被吃满。把分辨率降一档,把帧率降到 24,再看指令生效时间。如果降完仍然堆积,检查是不是每帧都在提交指令——指令应该有节流,而不是跟着帧率跑。
主体一直在变脸或换衣服。这是改视频里最常见的一致性问题。加参考图,加首帧锁定,并在指令里显式声明"保留其他区域不变"。风格类修改通常比几何类修改更稳,可以先跑风格验证链路。
提示词越改越乱。实时场景下连续发多条指令,模型来不及收敛,画面会在几个状态之间抖。做法是加一个稳定窗口:一条指令生效后,等画面稳定再接受下一条,或者用指令队列按顺序消费。
空间视频边缘出现拉伸或鬼影。看源素材:快速运动、大面积遮挡变化、镜面反射这三类情况都会让深度解算不稳。换一段运动平缓的素材,效果通常明显变好。
空间视频转出来的场景转不了大角度。把环绕范围先收到较小角度,确认近处几何正常,再逐步放宽。一圈圈放,比一次放到很大更容易定位问题。
任务一直排队或超时。检查并发配额和素材时长上限,这两个限制在实时和异步接口上往往不一样。具体数值以官方页面的说明为准。
下一步建议
跑通之后,往这三个方向走:
一是把提示词模板做成配置。四段式模板存成 JSON,前端只暴露几个输入框,非技术同事也能自己改词,你只维护模板结构。
二是建一个小评测集。固定十段素材、十张参考图、十条指令,每次调整参数都跑一遍,记录主体一致性、边缘干净度、指令生效时间。有基线才能判断改动是变好还是变坏。
三是做降级策略。实时链路一定要有"连不上就退回低分辨率"和"失败自动重连一次"的两级兜底,演示场合断流一次,后面解释成本很高。
具体的能力边界、额度与接口细节,以 Vidu 官方文档当前版本为准。
