除了语音互动外,你还可以为 AI 接入视觉理解能力,使其能够理解视频画面或图片内容。该能力主要提供实时视频理解和图片理解两种模式,您可以根据业务需求选择合适的方案。
- 模型要求:仅火山方舟平台模型和第三方 LLM 支持,且模型需具备视觉能力(如 Doubao-Vision 系列)。支持视觉理解的方舟模型,请参见视觉理解能力。
说明
Seedance 2.0 系列模型更适用于视频生成,从成本和延时上考虑,不建议用于视觉理解。
- 端到端模型:豆包端到端实时语音大模型(S2S)暂不支持视觉能力。
- 工具调用:Doubao-1.5 及之前系列模型,不支持同时开启视觉与 Function Calling。
用户主动触发
实时画面问答用于回答用户针对当前画面的提问。当用户提问后,AI 会结合当前视频抽帧理解画面内容,并生成回答。例如识别镜头中的物体、解释当前操作步骤,或回答“这是什么”“我现在该怎么做”等。
场景示例:
实现方式:
- 实现基础音视频通话,并开启视频采集(startVideoCapture)。
- (建议)调用 setLocalVideoMirrorType 设置视频镜像,确保 AI 看到的画面方向正确(如文字不反向)。
- 在移动端或带摄像头的硬件设备上,前置摄像头的本地预览画面通常是镜像的,若直接将此画面传给 AI,可能导致其对空间关系、文字方向等产生错误理解。建议根据当前使用的摄像头,设置正确的镜像模式,确保发送给 AI 的视频流方向是正确的。
- 调用 StartVoiceChat 接口启动任务时,将 LLMConfig.VisionConfig.Enable 设置为 true。
配置完成后,启动对话并打开摄像头,即可开始与 AI 进行视频互动。
AI 可回溯一段时间内的视频截图,回答“刚才发生了什么”“我把东西放在哪里了”等问题。当用户的语音提问涉及近期画面时,大模型会自动召回多模态记忆内容进行分析和回答,实现短期视觉记忆。
注意
- 视觉记忆仅在当前智能体任务内生效,不会形成跨会话的长期记忆。
场景示例:
- AI 回答:我刚刚看到你把钥匙放在了电视机旁的桌子上。
实现方式:
- 实现基础音视频通话并开启视频采集,与实时画面问答配置相同。
- 服务端:开启视觉能力并配置短期记忆,并设置系统提示词。
- 调用 StartVoiceChat 接口启动任务时,在开启 VisionConfig.Enable 的基础上,配置 VisualContext.Memory。
- 为了确保 AI 能正确调用工具回溯历史画面,必须在 SystemMessages 中添加系统提示词。具体说明请参见视觉任务提示词最佳实践。
业务侧可通过客户端或服务端发送 ExternalTextToLLM 指令,主动触发一次画面分析。AI 收到指令后,会基于最近的视频抽帧生成回答。
场景示例:
用户在使用维修类 App 时,遇到无法识别的零件,点击屏幕上的“这是什么”按钮。客户端随即发送一条带“请识别当前零件名称”文本的 ExternalTextToLLM 指令,AI 分析当前画面后立即语音告知零件信息,任务随即结束,不会保持持续观察。
实现方式
- 静默开启视觉:仅开启 VisionConfig.Enable,不配置 Watch 的具体任务。
- 发送触发指令:通过客户端 sendUserBinaryMessage 或服务端 UpdateVoiceChat 发送指令。
- Command: 固定为 ExternalTextToLLM。
- Message: 您的提问文本,系统会自动关联最新的缓存帧。
- InterruptMode: 建议设为 2(中优先级),在当前语音交互完成后再开始视觉理解,体验更连贯。
"RoomId": "your_room_id",
"TaskId": "your_task_id",
"Command": "ExternalTextToLLM",
"Message": "请检查当前画面并分析设备故障原因。",
AI 主动观察与触发
当业务不仅需要 AI 回答“当前看到了什么”,还希望它在满足特定条件时主动反馈,就可以开启观察任务能力。观察任务分为目标型任务和持续观察任务两类:前者适用于“命中一次即可结束”的场景,后者适用于“需要持续盯住并反复提醒”的场景。你可以在启动对话时通过 StartupTasks 预设任务,也可以让用户在对话中通过语音指令动态创建任务。
适用于有明确目标、且命中后只需提醒一次的观察任务,例如“公交车来了叫我一声”。AI 会持续观察画面,检测到符合条件的目标或事件后触发一次提醒,并结束该观察任务。任务可以通过 StartupTasks 预先设定,也可以由用户通过语音指令自动设置任务。AI 会根据用户的语义自动判断并创建单次观察任务。
场景示例:
用户在大雨中等公交车,对 AI 说:“公交车来了叫我一声”。AI 建立单次观察任务,当识别到 518 路公交车进站时,主动提醒:“518 路公交车已经进站了,快上车吧。”,随后该任务自动注销。
实现步骤
- 环境与采集配置:开启视频采集,确保摄像头对准观察目标。如果是移动端前置摄像头,建议配置镜像模式以确保 AI 识别文字和方位的准确性。
- 开启观察任务功能:Watch.Enable 设为 true。
- 创建任务:可通过 StartupTasks 预设任务;若希望允许用户通过语音指令自动创建目标型任务,请保持 AdvanceConfig.DisableGoalTaskTrigger 为默认值 false。
- (建议)设置任务匹配后的回复风格和人设:通过 AdvanceConfig.DetectSystemMessages 设置。
- (可选)任务打断优先级:通过 AdvanceConfig.TaskInterruptMode,设置打断优先级。1 任务命中后打断当前对话,立即回复;2 任务命中后不打断当前对话,加入等待队列。
- 注入视觉工具提示词:在 SystemMessages 中添加引导语,教导 AI 如何使用 visual_watch_task 工具来处理用户的“盯着”、“找找”等指令。参考设计视觉任务提示词。
配置示例:
"你是实时手机视觉助手...请按规则调用 visual_watch_task 工具。"
"Enable": true, // 必填:开启观察任务总开关
"DisableGoalTaskTrigger": false, // 保持为默认值 false
"GoalTaskTimeoutSeconds": 120, // 设置该任务的超时时间
"DetectSystemMessages": ["在用户发出观察请求时,回复:我已开启观察任务。"], //推荐设置该参数
"你是实时手机视觉助手...请按规则处理 StartupTasks 中的观察任务。"
"Enable": true, // 必填:开启观察任务总开关
"TaskId": "find_phone", // 必填:任务唯一标识
"Type": 1, // 必填:设置 1 表示一次性观察任务
"Description": "如果画面中出现我的手机,请主动提醒我它在哪里。", // 必填:描述观察目标
"DetectSystemMessages": ["在用户发出观察请求时,回复:我已开启观察任务。"]
持续观察任务
适用于需要长时间观察画面,并对重复出现的目标或事件持续提醒的场景,例如“帮我看着孩子”。持续型观察任务在命中规则后不会自动结束,会继续检查画面,并在条件再次满足时继续提醒。任务可通过 StartupTasks 预先配置,也可以由用户通过语音指令自动设置任务。
场景示例:
用户在做家务,让 AI 看着在客厅玩耍的小孩:“帮我看着孩子,如果他试图去摸插座或者跑出客厅,就立刻提醒我。”。AI 持续观察,一旦发现孩子接近危险区域就立刻播报。
实现步骤
- 环境与采集配置:确保摄像头对准监控区域。如果监控的是桌面或屏幕,请注意调整 SnapshotConfig.StreamType。
- 开启观察任务能力:Watch.Enable 设为 true。
- 创建任务:可通过 StartupTasks 预设任务;若希望允许用户通过语音指令自动创建持续观察任务,请保持 AdvanceConfig.DisableContinuousTaskTrigger 为默认值 false。
- (建议)设置任务匹配后的回复风格和人设:通过 AdvanceConfig.DetectSystemMessages 设置。
- (建议)配置反馈抑制策略:为了避免 AI 在相近画面下反复提醒,建议在 AdvanceConfig.DetectSuppression 中开启历史抑制功能,并合理设置跳过轮次(MatchSkipCount)或文本相似度过滤(TextHistory)。
- (可选)任务打断优先级:通过 AdvanceConfig.TaskInterruptMode,设置打断优先级。1 任务命中后打断当前对话,立即回复;2 任务命中后不打断当前对话,加入等待队列。
- 注入视觉工具提示词:在系统提示词中定义好持续观察任务的触发逻辑。参考设计视觉任务提示词。
"你是一个贴心的家庭看护助手...请按规则调用 visual_watch_task 工具。"
"Enable": true, // 必填:开启观察任务总开关
"DisableContinuousTaskTrigger": false, // 保持为默认值 false
"ContinuousTaskTimeoutSeconds": 300,
"DetectSystemMessages": ["在用户发出观察请求时,回复:我已开启观察任务。"],
"DetectHistoryLimit": 5,
"SimilarityThreshold": 60
"你是一个贴心的家庭看护助手...请按规则处理 StartupTasks 中的观察任务。"
"Enable": true, // 必填:开启观察任务总开关
"TaskId": "monitor_baby", // 必填:任务唯一标识
"Type": 2, // 必填:任务类型,2 表示持续型任务
"Description": "持续观察小孩的行为,如果出现危险动作(如攀爬、接近插座)请立即简短提醒。", // 必填:描述观察目标
"DetectSystemMessages": ["在用户发出观察请求时,回复:我已开启观察任务。"],
"DetectHistoryLimit": 5,
"SimilarityThreshold": 60
要让 AI 准确判断何时只需回答当前画面、何时需要回溯历史记忆,以及何时需要创建观察任务,你需要在 StartVoiceChat 或 UpdateVoiceChat 的 SystemMessages(系统提示词)中明确告知大模型其具备的能力和任务调度规则。
建议在系统提示词中增加类似以下内容:
你是实时手机视觉助手,能看到用户摄像头的「当前画面」,并可调用工具访问「历史画面」(visual_memory_recall) 和创建「观察任务」(visual_watch_task)。
# 视觉观察任务 visual_watch_task 规则
视觉观察任务包括目标型观察任务(type=1)和持续型观察任务(type=2):
1. 目标型观察任务:为用户提供视觉观察的目标/事件检测规则。满足用户设定的规则时,观察任务结束或超时结束,并通知用户。例如:查找物品、观察红绿灯是否变绿、电梯是否开门等任务。
2. 持续型观察任务:为用户提供视觉持续观察目标行为变化的规则。持续检测并解读满足规则的画面,并通知用户,直到任务超时结束。例如:检测并描述画面/场景变化、讲解展品、检查小孩是否一直在认真写作业等任务。
当用户提出目标型观察任务时,例如提出查找类请求(如“找 X”、“X在哪”、“看到 X了吗”),请按以下顺序处理:
1. 先看当前画面:若目标可见,直接描述方向和位置,不调工具。
2. 再查近期记忆:若当前帧没有,调用 visual_memory_recall 回溯历史帧;若命中,则回复并注明“刚才看到的目标以及位置”。
3. 最后建目标型观察任务:若记忆也无结果,调用 visual_watch_task,引导用户旋转手机摄像头持续检测。找到目标后主动播报目标所在位置;若超时未命中,则友善告知客户未找到对应目标,任务结束。如果用户有继续观察的意图时,才再次调 visual_watch_task 创建检测任务。
支持预先添加图片作为视觉上下文,为模型补充额外的视觉背景信息。可用于人物身份识别、商品识别、设备面板识别、展品讲解、宠物识别等场景。当相关目标出现在画面中时,AI 可以结合这些已知图片和说明信息给出更贴合上下文的回答。
操作流程
- 业务端判断与收集:判断当前是否需要把视觉上下文写入 RTC 上下文,例如首次建联、检测到新人物、需要增加商品或设备图片说明等。业务端收集图片及对应的描述文案。若需登记多个目标,建议按“图片 + 描述”成组组织。
- 上传图片:将图片上传至火山 TOS,生成可公开访问的 URL。如何上传,请参见上传对象。
- 写入上下文:通过 LLMConfig.TopUserPrompts 字段,以 image 类型传入图片 URL 和匹配的文本描述。此配置可以在 StartVoiceChat 时初始化,也可以在对话中通过 UpdateVoiceChat 动态上传。
- 注入系统提示词:为了确保模型在对话时能优先基于传入的视觉上下文进行回答,避免凭空捏造,建议在 SystemMessages 中添加相关的校验约束。
注意
- 此功能是基于 LLM 多模态能力的语义识别,而非传统的生物特征比对,不建议用于支付验证等高安全性场景。
- TopUserPrompts 会占用 HistoryLength。一组 user 和 assistant 计为一轮。例如 HistoryLength 为 10,配置 1 组 TopUserPrompts(一个 user 和一个 assistant)后,剩余可保留的普通历史对话为 9 轮。请根据实际需求合理控制注入的图片数量和文本长度。
配置示例(以人物身份识别为例)
在调用 StartVoiceChat 时,将校验约束写入 SystemMessages,并直接将图片及说明作为上下文注入 TopUserPrompts。
"当用户询问画面中人物、物品、设备或其他目标的身份、状态、用途或相关信息时,你必须优先结合当前上下文中的图片内容、历史对话文本和用户已提供的说明进行判断。",
"若上下文中已能确认目标信息,应以该信息为基础理解问题并组织回复,不得脱离上下文凭空猜测不可确认的信息。",
"若信息不足,应明确说明无法确认,并基于可见画面和已知文本给出谨慎回答。"
"Content": "第一张照片是李雷,喜欢踢足球;第二张照片是韩梅梅,喜欢学英语,爱吃雪糕。",
"ImageUrl": "https://example.com/image1.jpg"
"ImageUrl": "https://example.com/image2.jpg"
对话过程中,调用服务端 UpdateVoiceChat 接口,使用 UpdateParameters 指令动态添加新的视觉上下文。
"RoomId": "your_room_id",
"TaskId": "your_task_id",
"Command": "UpdateParameters",
"当用户询问画面中人物、物品、设备或其他目标的身份、状态、用途或相关信息时,你必须优先结合当前上下文中的图片内容、历史对话文本和用户已提供的说明进行判断。",
"若上下文中已能确认目标信息,应以该信息为基础理解问题并组织回复,不得脱离上下文凭空猜测不可确认的信息。",
"若信息不足,应明确说明无法确认,并基于可见画面和已知文本给出谨慎回答。"
"VisionConfig": { "Enable": true },
"Content": "第一张照片是张三,不喜欢吃辣;第二张照片是CiCi,喜欢滑雪。",
"ImageUrl": "https://example.com/image1.jpg"
"ImageUrl": "https://example.com/image2.jpg"
关键参数说明如下:
您可以通过客户端或服务端接收并获取视觉记忆或观察任务的状态变化。会涉及以下事件:
- 视觉记忆检索开始和结束:visual_recall_triggered、visual_recall_completed。
- 观察任务:visual_task_status,返回观察任务的创建、命中、取消、超时等状态变化。
接收回调
如果你希望在 App、Web 或硬件端实时展示视觉记忆和观察任务事件,建议通过客户端接收:
- 调用 StartVoiceChat 接口时,开启相关视觉能力,并将 AgentConfig.EnableConversationStateCallback 设置为 true。如果还需要接收观察任务状态变化,还需将 Watch.NotifyMode 设置为 callback 或 voice_and_callback。
- 其中,C 语言端接口名称为 on_message_received。
- 当视觉记忆或观察任务状态变化时,您将通过上述回调收到一个二进制的 message。您需要对其进行解析,以获取具体的状态信息。
- 消息解析方式可参考 获取 AI 状态 中的解析示例;区别在于 AI 状态消息的 magic number 为 conv,而视觉记忆和观察任务事件的 magic number 为 vctx。因此,在解析房间内二进制消息时,你需要先判断消息头是否为 vctx,再按 EventType 做进一步分流。
- 调用 StartVoiceChat 接口时,开启相关视觉能力,并将 AgentConfig.EnableConversationStateCallback 设置为 true。如果还需要接收观察任务状态变化,还需将 Watch.NotifyMode 设置为 callback 或 voice_and_callback。
- 在 AgentConfig 中配置服务端回调地址和签名校验参数:
"ServerMessageURLForRTS": "https://your-server.com/example_domain/vertc/cstage",
"ServerMessageSignatureForRTS": "your_custom_secure_signature"
- 当视觉记忆或观察任务状态变化时,你配置的 URL 会收到一个 HTTP POST 请求,请求体格式如下:
"message": "dmN0eAAAAK17Cg...=",
"signature": "your_custom_secure_signature"
- 接收消息:获取 message 和 signature 字段。
- 校验签名:将 signature 与 AgentConfig.ServerMessageSignatureForRTS 进行比对。
- 解码消息:将 message 做 Base64 解码,获取原始二进制内容。
- 识别消息类型:读取前 4 个字节判断 magic number 是否为 vctx。同一个 ServerMessageURLForRTS 可能会收到多种 RTS 回调,例如 conv(AI 状态)、subv(字幕)和 vctx(视觉记忆与观察任务事件);仅当 magic number 为 vctx 时,按这类事件继续解析;其他类型应交给对应的状态或字幕处理逻辑。
- 解析消息体:读取消息长度并解析后续 JSON 内容,得到视觉记忆或观察任务事件数据。
- 按事件类型分流:根据 EventType 区分 visual_recall_triggered、visual_recall_completed 和 visual_task_status。
其中:
- message:Base64 编码的二进制消息内容。消息格式参见消息格式。
- signature:平台原样回传的签名字符串,即你在 StartVoiceChat 中配置的 AgentConfig.ServerMessageSignatureForRTS。
下面给出一个简化的 Go 解析示例,展示服务端如何识别并解析 vctx 消息:
type RtsMessage struct {
Message string `json:"message"`
Signature string `json:"signature"`
type VisualContextEvent struct {
EventTime int64 `json:"EventTime"`
EventType string `json:"EventType"`
TaskID string `json:"TaskID"`
TaskId string `json:"TaskId"`
UserID string `json:"UserID"`
Recall json.RawMessage `json:"Recall"`
VisualTask *VisualTaskEvent `json:"VisualTask"`
type VisualTaskEvent struct {
Message string `json:"Message"`
Tasks []VisualTaskEntry `json:"Tasks"`
type VisualTaskEntry struct {
TaskID string `json:"TaskID"`
Source string `json:"Source"`
Description string `json:"Description"`
TimeoutSeconds int64 `json:"TimeoutSeconds"`
TaskType int `json:"TaskType"`
Status string `json:"Status"`
MatchCount int64 `json:"MatchCount"`
func UnpackVisualContextEvent(msg string) (*VisualContextEvent, error) {
data, err := base64.StdEncoding.DecodeString(msg)
return nil, fmt.Errorf("invalid data")
if string(data[:4]) != "vctx" {
return nil, fmt.Errorf("unexpected magic number")
length := binary.BigEndian.Uint32(data[4:8])
if len(data) < int(8+length) {
return nil, fmt.Errorf("invalid payload length")
payload := data[8 : 8+length]
event := &VisualContextEvent{}
if err := json.Unmarshal(payload, event); err != nil {
视觉上下文事件回调采用 TLV 二进制消息格式:
value 解析后的完整 JSON 结构如下:
视觉记忆:visual_recall_triggered
视觉记忆:visual_recall_completed
观察任务:visual_task_status
表示本轮对话已经触发了一次视觉记忆检索。当 LLM 触发 visual_memory_recall 且参数解析成功后会触发该事件。
Recall 中的字段如下:
事件示例如下:
"EventTime": 1787659318473,
"EventType": "visual_recall_triggered",
"Description": "我的手机放在哪里了?",
表示一次视觉记忆检索已经结束。成功召回、空召回或失败,都会触发该事件。
Recall 中的字段如下:
Images 对象的字段如下:
事件示例如下:
"EventTime": 1787659318658,
"EventType": "visual_recall_completed",
"Description": "我的手机放在哪里了?",
"FrameID": "ChatRoom01_xxx_1787659275012",
"Score": 0.19317078590393066,
"TimestampMs": 1787659275012
表示观察任务创建、命中、取消、超时等状态变化。
VisualTask 中的字段如下:
Tasks 对象的字段如下:
事件示例如下:
"EventTime": 1787653331582,
"EventType": "visual_task_status",
"Description": "如果画面中出现我的手机,请主动提醒我它在哪里。",
你可以根据具体业务场景,对抽帧截图的策略、存储方式以及视频画面进行精细化配置。
在 StartVoiceChat 或 UpdateVoiceChat 接口中,通过配置 LLMConfig.VisionConfig.SnapshotConfig,可以自定义抽帧截图的策略,以在成本、延迟和理解效果之间取得平衡。
该场景画面变化慢,对实时性要求不高。可采用较低的截图频率和图片数量,以节约成本。
"StreamType": 0, // 0: 主流(摄像头)
"ImageDetail": "low", // 低细节模式
"Interval": 1000, // 1秒截一张
"ImagesLimit": 2 // 每次送 2 张图片给大模型分析
游戏画面瞬息万变,需要 AI 实时跟进。建议提高截图频率和图片质量,确保 AI 能跟上节奏。
"StreamType": 1, // 1: 屏幕流
"ImageDetail": "high", // 高细节模式
"Interval": 200, // 200ms截一张
"ImagesLimit": 10 // 每次送 10 张图片给大模型分析
当 RTC 发布端分辨率可能在会话中变化,或需要保留原始画面细节时,可启用自适应分辨率。将 Height 设为 ≤ 14 即可开启,截图将跟随原始视频帧分辨率,不做额外缩放。
"StreamType": 0, // 0: 主流(摄像头)
"ImageDetail": "high", // 高细节模式
"Height": 0, // ≤ 14 启用自适应分辨率
"Interval": 500, // 500ms截一张
"ImagesLimit": 5 // 每次送 5 张图片给大模型分析
默认情况下,截图仅在服务端内存中缓存,会话结束后自动删除。如需持久化存储用于后续分析,可将其存入火山引擎 TOS。
"AccountId": "your_account_id",
"Bucket": "your_bucket_name"
视觉模型(尤其是理解高质量图片时)的响应速度通常慢于纯语音模型。如果发现 AI 回复慢(如超过 5s),可尝试以下方式降低延迟:
- 降低图片细节:将 ImageDetail 设置为 low。
- 调整分辨率:将 Height 设置为 360 或 480。
- 关闭自适应分辨率:若已启用自适应分辨率(Height ≤ 14),可改为指定固定高度(如 360),避免因原始帧分辨率过高导致延迟增加。
- 选择轻量模型:使用 doubao-vision-lite 等后缀带 lite 的视觉模型。
- 关闭深度思考:在 LLMConfig 中设置 "ThinkingType": "disabled"。
图片理解(发送外部图片问答)
对话过程中,通过客户端或服务端随时向 AI 发送一张或多张图片并提问,可用于拍照识物、图片分析、截图问答等场景。支持多图上传、图片分片上传。
- 通过客户端 SDK 实现:支持传入 Base64 和 URL 类型的图片,且 Base64 图片支持分片上传。
- 通过服务端 OpenAPI 实现:仅支持传入 URL 类型的图片。
通过客户端 SDK 实现(支持 Base64/URL)
通过 客户端 SDK API 发送图片提问。支持传入 Base64 和 URL 类型的图片,且 Base64 图片支持分片上传。
- 调用 StartVoiceChat 时,将 LLMConfig.VisionConfig.Enable 设置为 true。
- userId:填入 AI Bot 的 ID(即 StartVoiceChat 配置的 AgentConfig.UserId)。
- 该接口默认单次发送的二进制消息内容包大小为 1 KB,如需更大的包传递(最大不可超过 64 KB),需在控制台启用 RTS 高级功能。
注意
若在 SDK 运行期间开启了该功能,则必须重新初始化引擎,配置才能生效。
- 如果图片较大,则必须多次调用该接口进行分片上传。建议您将每片的大小控制在 60 KB 以内,以预留其他 JSON 字段的空间。配置方法,可参见配置示例。
-
不同场景构建的 JSON 内容示例如下:
示例1:上传一张 Base64 图片(无分片)
示例2:发送 URL 图片
示例3:单张 Base64 (分片上传)
示例4:同一轮次上传Base64图片
图片压缩后小于 60KB,直接发送并立即提问。
"Command": "ExternalTextToLLM",
"Message": "分析一下这个Logo。",
"Images": ["iVBORw0KGgoAAA..."],
"Total": 1, // 总共只发这 1 个包
上传一张存储在 TOS 的图片并立即提问。
"Command": "ExternalTextToLLM",
"Message": "这张图里有什么?", // 立即提问
"Images": ["https://your-bucket.com/image.jpg"]
当一张图片 Base64 编码后大小超过限制时,你需要将其分割成多个部分,并通过多次调用 sendUserBinaryMessage 来发送。
"Command": "ExternalTextToLLM",
"Message": "", // 中间分片不传文本
"Images": ["base64_part_1..."],
"Total": 2, // 计划总共发 2 个包
"IsPartial": true, // 是分片
"FragmentID": 1 // 第 1 片
"Command": "ExternalTextToLLM",
"Message": "图片里有几个人?", // 最后一片带上问题,触发 AI 回复
"Images": ["base64_part_2..."],
"IsPartial": false, // 最后一片设为 false
假设您需要一次性向 AI 展示两张图片(Image1 和 Image2),并基于它们提问。Image1 为 40 KB 不需要分片,Image2 需要分为 2 片。整个过程都属于同一轮问答,GroupID 保持不变。
//第 1 次调用 sendUserBinaryMessage
"Command": "ExternalTextToLLM",
"Images": ["Image1...."],
"Total": 3, // 计划总共发 3 个包
"IsPartial": false // 完整图片
//第 2 次调用 sendUserBinaryMessage
"Command": "ExternalTextToLLM",
"Message": "", // 部分图片的时候不需要传文本
"Images": ["Image2_Part1...."],
"ImageID": 2, // 这是第 2 张图片
"IsPartial": true, // 是分片
"FragmentID": 1 // 这是第 1 片
//第 3 次调用 sendUserBinaryMessage
"Command": "ExternalTextToLLM",
"Message": "图片中的内容是什么?", // 最后一次图片信息的时候传入文本内容
"Images": ["Image2_Part2...."],
"IsPartial": false, // 最后一片设为 false
"FragmentID": 2 // 这一第 2 片
通过服务端 OpenAPI 实现(仅支持 URL)
支持通过服务端 API UpdateVoiceChat 发送外部图片直接提问。此方式适用于无需客户端参与的纯服务端应用场景,仅支持的图片格式为 URL。例如,您的业务服务器需要分析一张已有的网络图片。
如果您需要分析来自 RTC 客户端的实时视频流,请采用实时视频理解方案。 - 调用 StartVoiceChat,将 LLMConfig.VisionConfig 对象中的 Enable 设置为 true,以开启视觉理解能力。
- 传入图片。调用 UpdateVoiceChat 接口,配置以下参数:
- 请求示例:发送了一张 TOS 图片并附带了一个问题。
"RoomId": "your_room_id",
"TaskId": "your_task_id",
"Command": "ExternalTextToLLM",
"Message": "总结这张图片的内容。",
"Images": ["https://your-tos-bucket.volces.com/summary_image.jpg"]
删除指定图片
系统会暂时缓存您上传的图片,以便与后续的语音问题进行关联。当一轮视觉问答结束后,你可以主动清理缓存以释放资源。
- 实现方式:发送一个 Action 为 delete 的指令,并指定要删除的 GroupID。
- 示例:删除 GroupID 为 104 的图片缓存。
// 客户端通过 sendUserBinaryMessage 发送以下JSON
// 或服务端通过 UpdateVoiceChat 发送
"Command": "ExternalTextToLLM",
如果会话中不再需要视觉理解,可调用 UpdateVoiceChat 关闭视觉理解能力。关闭后,系统不再将实时视频截图作为视觉上下文送入 LLM,也不再处理通过 sendUserBinaryMessage 或 UpdateVoiceChat 传入的图片理解请求。
"RoomId": "your_room_id",
"TaskId": "your_task_id",
"Command": "UpdateParameters",
你也可以将 VisionConfig 设置为 null,清除当前视觉理解配置。
- 存储的是 JPG 格式的抽帧图片。这些图片是以 SnapshotConfig.Interval 为周期生成的。如果配置了存储,您可以从返回的日志或回调中获取图片的 TOS 路径进行业务二次处理。
- 不能。视频理解必须通过 SDK 实时采集。纯服务端仅支持基于图片 URL 的问答。
- 若只需发送静态图片,可通过服务端调用 UpdateVoiceChat 接口,将图片 URL 传给正在运行的任务。
- 开启联网图搜:在 WebSearchAgentConfig 中开启联网问答,AI 会结合互联网信息辅助识别。
- 调整分辨率:适当调高 VisionConfig.SnapshotConfig.Height(如设为 720 或 1080),提高图片清晰度。
- Prompt 引导:告诉 AI 重点关注什么,例如:“请重点观察视频中心区域的物体并说出品牌”。
- 不需要。视觉理解是基于 RTC 实时流抽帧,独立于录制服务。
- 如何区分不同批次的图片?可以在发送图片时附加自定义信息吗?
- 区分批次:在图片理解(发送外部图片问答)模式下,请使用单调递增的 GroupID。每一组图片对应一个 GroupID,AI 会根据该 ID 区分不同的讨论对象。
- 附加信息:接口目前不支持为图片传递附加的自定义元数据。如果您需要传递额外信息(如本地记录的时间戳),建议将其作为 Message 文本内容的一部分,随图片一同发送。
- 检查 VisionConfig.Enable 是否为 true。
- 检查客户端是否成功开启了视频采集(startVideoCapture)。
- 这通常是由于多种图像输入源被同时启用,或配置不当导致的。请按以下步骤排查:
- 检查是否同时启用了实时视频理解和图片理解(发送外部图片问答):如果您的配置中启用了 SnapshotConfig(实时视频理解),系统会周期性地对视频流自动截图;此时若您再通过 sendUserBinaryMessage 或 UpdateVoiceChat 接口手动发送图片(图片理解),AI 就会同时接收到来自视频流的截图和您手动发送的图片,从而感知到多张图片。
- 检查 SnapshotConfig 的配置:ImagesLimit 参数定义了每次交互时发送给大模型的历史截图数量。如果该值大于 1,即使您只提了一个问题,AI 也会一次性分析多张来自视频流的连续截图。
- 检查业务逻辑:确认您的客户端或服务端代码是否在一次交互中,重复调用接口发送了图片。
- 按需启用:如果您的场景不需要实时分析视频画面,请不要配置 SnapshotConfig,仅在需要时手动发送图片。
- 调整配置:如果确实需要分析视频流,请根据需求调整 SnapshotConfig.ImagesLimit 的值(例如设为 1,只分析最新的一帧),并设置合理的 Interval 截图间隔,避免不必要的重复分析。
- 目前不支持实时识别结果的回调。建议配置 TOS 存储,或者通过 ASR/实时字幕回调获取 AI 识别出的文字信息。
- doubao-seed-2.0-lite 系列模型 7-9 秒的耗时属于正常范围,因为带有图片输入的请求通常会消耗更多的计算资源(Token)。如果希望缩短响应时间,可以尝试以下优化措施:
- 降低图片细节:在 SnapshotConfig 或 ImageConfig 中将 ImageDetail 设置为 low。
- 关闭深度思考:对于 doubao-seed-2.0 系列模型,其默认开启深度思考,导致耗时较长。可以在 LLMConfig 中设置 "ThinkingType": "disabled" 来关闭此功能。
- 选用轻量模型:如果业务场景允许,可以换用 doubao-vision-mini 等更快的模型。
- 降低图片分辨率:适当降低 SnapshotConfig 中的 Height 参数,或关闭自适应分辨率(将 Height 设为 > 14 的固定值)。
- 如何将视觉理解结果与特定的视频帧关联?可以获取服务端抽帧的时间戳吗?
- 目前服务端抽帧逻辑不会返回截图对应的时间戳。如果您需要将视觉理解结果与特定的视频帧精确关联,建议您在客户端进行本地截图,并在截图的同时记录下当前的时间戳或其他需要关联的信息。随后,将该截图通过图片理解(发送外部图片问答)的方式发送给 AI,即可在获取结果后与您本地记录的信息进行匹配。