移动端Android SDK

本文介绍了如何使用阿里云百炼大模型服务提供的实时多模交互移动端 Android SDK,包括SDK下载安装、关键接口及代码示例。

MultiModalDialog SDK是阿里云通义团队提供的支持音视频端到端多模实时交互的SDK。通过SDK对接通义大模型以及后端多种Agent,能够支持用户接入语音对话、天气、音乐、新闻等多种能力,并支持视频和图像的大模型对话能力。

多模态实时交互服务架构

多模态实时交互服务接入架构-通用-流程图

前提条件

  • 开通阿里云百炼实时多模交互应用,获取Workspace IDAPP IDAPI Key

  • 下载SDK和 Demo bailian-multi-modal-android-sdk-1.0.4.1.zip并配置必要的环境、依赖。

  • 导入示例代码,按照调用流程接入SDK。

  • 您可以直接运行压缩包中的 APK 测试程序,填入上方三个必要参数,即可进行测试。

SDK接入

交互数据链路说明

SDK支持WebsocketRTC 两个链路与服务端交互,多模交互支持AudioOnlyAudioAndVideo 两种模式:

  • 音频交互:推荐使用Websocket 连接,连接速度较快,性能要求较低。

    • WS 链路音频格式说明:

      • 上行:支持 pcm 和 opus 格式音频进行语音识别。

      • 下行:支持 pcm 和 mp3 音频流。

  • 音视频交互:仅支持RTC 传输方式连接进行交互,提供端到端的音视频多模交互能力。

    • RTC 链路音频格式说明:

      • 上行:支持 pcm 传入 SDK,传输采用 opus 格式。

      • 下行:支持从 SDK 获取 pcm,传输采用 opus 格式。

交互模式说明

SDK支持 Push2TalkTap2TalkDuplex(全双工)三种交互模式。

  • Push2Talk: 长按说话,抬起结束的收音方式。

  • Tap2Talk: 点击开始说话,自动判断用户说话结束的收音方式。

  • Duplex: 全双工交互,连接开始后支持任意时刻开始说话,支持语音打断。

调用说明

SDK及其调用Demo。

SDK引用

导入依赖库。

  • app/src/main/libs

    • convsdk-release_*.aar //阿里云VoiceChatSDK

    • multimodal_dialog_sdk.aar // 阿里云多模对话SDK

    • com.aliyun.aio:AliVCSDK_ARTC // 阿里云RTC SDK

  • 其他DemoAPP引入的依赖:

    参考app/build.gradle

    implementation libs.androidbootstrap
    implementation libs.okhttp
    implementation libs.okio //Android OKHttp3应用要增加一个收入IOokio包
    implementation libs.http.logging.interceptor
    implementation libs.core.ktx
    //导入视频云sdk
    implementation libs.alivcsdk.artc

关键参数

参数名称

是否必须

说明

url

String

请求的服务端地址。

Websocket链路地址:wss://dashscope.aliyuncs.com/api-ws/v1/inference

RTC链路地址:

https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation

api_key

String

百炼服务接入API Key 请您在百炼平台创建API_KEY,移动端为了安全考虑,您也可以在服务端接入短时Token,并下发给客户端使用。

workspace_id

String

百炼管控台,工作空间id。

app_id

String

您在管控台创建的应用id。

chain_mode

String

RTC/Websocket。

Demo简介

  • EntranceActivity 入口页面,需要修改url/api_key/app_id等信息。

    • 可以通过页面选择使用RTC或者Websocket请求链路。

    • 可以通过页面选择对话使用Tap2Talk或者Duplex等模式。

  • MultimodalDialogActivity,对话交互实现类。

    • Demo页面中引用TYAudioRecorder 作为录音输入,您可以替换为自己的实现。

    • Demo页面使用AudioPlayer作为音频播放输出,您可以选择使用自己的实现类。

    • Demo在音频交互模式下,支持VQA(图生文)功能,即通过语音说“拍照识别xxx”,触发服务下发拍照意图。之后:

      • 您可以将本地拍照并上传OSS(或其他内容服务生成公共链接),触发单张图片的识别和对话。

      • 您也可以直接上传图片的base64请求服务或者图片的对话结果。

    • DemoVideoAndAudio音视频交互模式下,目前通过外部采集的方式输入图像序列,方便眼镜等IoT设备的采集和视频对话接入。

接口设计

MultimodalDialog 对话入口类
  1. MultiModalDialog

    初始化对话类,传入必要的全局参数。

    /**
         * 初始化     
         * @param context: 上下文
         * @param url: 服务器地址
         * @param chainMode: 链路模式
         * @param workspaceId: 工作空间id
         * @param appId: 应用id
         * @param dialogMode: 对话模式
         * */
        fun MultiModalDialog(
            context: Context,
            url: String?,
            chainMode: ChainMode?,
            workspaceId: String?,
            appId: String?,
            dialogMode: DialogMode?
        )
  2. createConversation

    创建会话。

    /**
         * 初始化成功后,启动对话流程
         * @param params 初始化参数
         * @param chatCallback 主回调,除了初始化过程的所有消息,都会从这里透出给上层
         */
        fun createConversation(@NonNull MultiModalRequestParam params,chatCallback: IConversationCallback)
  3. start

    开始对话。

    /**
         * 连接,启动对话
         */
        fun start()
  4. stop

    结束对话。

    /**
         * 断开,结束对话
         */
        fun stop()
  5. destroy

        /**
         * 销毁实例
         */
        fun destroy()
  6. setConversationTimeout

    设置超时时间。

        /**
         * 设置对话超时时间,当服务未在指定时间内检出用户说话,上报timeout事件
         * @param timeout 超时时间,单位ms
         */
        fun setConversationTimeout(timeout: Long)
  7. interrupt

    打断交互。

        /**
         * 打断AI说话
         */
        fun interrupt()
  8. startSpeech

    通知服务端开始上传音频,注意需要在Listening状态才可以调用。只需要在Push2Talk模式下调用。

    /**
     * 通知服务端开始上传音频,注意需要在Listening状态才可以调用。
     * 只需要在Push2Talk模式下调用。
     */
    fun startSpeech()
  9. sendAudioData

    通知服务端上传音频。

    /**
     * 通知服务端上传音频。
     * @param audioData 音频帧数据
     */
    fun sendAudioData(audioData: ByteArray?)
  10. stopSpeech

    通知服务端结束上传音频。只需要在Push2Talk模式下调用。

    /**
     * 通知服务端结束上传音频。只需要在Push2Talk模式下调用。
     * Push2Talk 用户结束说话
     */
    fun stopSpeech()
  11. requestToRespond

    请求服务端回答指定问题orTTS播放出来。

    /**
         * 请求服务端回答指定问题orTTS播放出来
         * @param type: transcript 表示直接把文本转语音,prompt 表示把文本送大模型回答
         * @param text:对应的文本
         * @param params: 额外参数
         */
        fun requestToRespond(type: String, text: String, params: JSONObject)
  12. 其他接口。

        /**
         * 当前配置是否是全双工模式
         */
        fun isDuplexMode(): Boolean
    
        /**
         * Push2Talk 用户取消说话
         */
        fun cancelSpeech()
    
        /**
         * 发送语音回复结束
         * */
        fun sendResponseEnded()
        
        /**
         * 发送语音回复开始
         * */
        fun sendResponseStarted()
    
        /**
         * 推送视频帧
         *
         * @param videoFrame 视频帧
         * @param callback: 送帧结果回调
         */
        fun sendVideoFrame(videoFrame: TYVideoFrame,callback: IVideoChatPushFrameCallback)
    
    
        
关键参数枚举
参数

说明

ChainMode

Websocket

仅支持AudioOnly

RTC

支持AudioOnlyAudioAndVideo两种交互

DialogMode

TAP2TALK

手动开始,自动结束

PUSH2TALK

手动开始,手动结束

DUPLEX

全双工交互

MultiModalRequestParam 端云交互参数详情
Start - Input Message

请求开始会话消息。服务收到Start消息后,向客户端发送Started消息。

一级参数

二级参数

三级参数

四级参数

类型

是否必选

说明

task_group

任务组名称,固定为"aigc"

task

任务名称,固定为"multimodal-generation"

function

调用功能,固定为"generation"

model

阿里云百炼模型名称,固定为"multimodal-dialog"

input

directive

string

指令名称:Start

workspace_id

string

客户在阿里云百炼业务空间ID(Workspace ID),可在百炼管控台“业务空间详情”中查看,目前仅支持主账号默认工作空间

app_id

string

客户创建的应用ID(APP ID),可在多模态交互管控台“我的应用”页面查看

dialog_id

string

对话ID,默认不填为开启新会话,服务端会自动生成并在事件中下发,格式为"12345678-1234-1234-1234-1234567890ab",共36个字符。当希望继续之前的对话时,把当时服务端下发的dialog_id在这里传入。

parameters

upstream

type

string

上行类型:

AudioOnly 仅语音通话

mode

string

客户端使用的模式,可选项:

  • push2talk: 端侧控制模式,由用户控制开始/结束端侧语音发送和识别,适用于按键说话,松开停止说话的场景。

  • tap2talk: 点击模式,需要客户端持续上传音频数据,由服务端vad检测语音开始和结束,但不支持用户说话打断大模型输出,只能发送打断消息

  • duplex: 双工模式,需要客户端持续上传音频数据,由服务端vad检测语音开始和结束,用户随时可以说话打断大模型输出

默认tap2talk

audio_format

string

音频格式,支持pcm,opus,raw-opus,默认为pcm

注意:opus 和 raw-opus的区别是opus格式的每一包数据都需要额外加ogg封装

sample_rate

int

语音识别的采样率,支持范围:

  • 8000

  • 16000

  • 24000

  • 48000

默认为16000

downstream

voice

string

合成语音的音色,支持范围取决于用户在管控台选择的tts模型

sample_rate

int

合成语音的采样率,支持范围:

  • 8000

  • 16000

  • 24000

  • 48000

默认为24000

audio_format

string

音频格式,支持pcm,opus,mp3,raw-opus,默认为pcm

注意:opus 和 raw-opus的区别是opus格式的每一包数据都有额外ogg封装

frame_size

int

合成音频的帧大小,取值范围:

  • 10

  • 20

  • 40

  • 60

  • 100

  • 120

默认值为60,单位ms

只在合成音频格式为opusraw-opus时生效

volume

int

合成音频的音量,取值范围0-100,默认50

speech_rate

int

合成音频的语速,取值范围50-200,表示默认语速的50%-200%,默认100

pitch_rate

int

合成音频的声调,取值范围50-200,默认100

bit_rate

int

合成音频的比特率,取值范围:6~510kbps,默认值为32,单位kbps,只在合成音频格式为opusraw-opus时生效

intermediate_text

string

控制返回给用户哪些中间文本:

  • transcript:返回用户语音识别结果

  • dialog:返回对话系统回答中间结果

可以设置多种,以逗号分隔,默认为transcript

transmit_rate_limit

int

下发音频发送速率限制,单位:字节每秒

client_info

user_id

string

终端用户ID,客户根据自己业务规则生成,用来针对不同终端用户实现定制化功能。最大长度40个字符。

device

uuid

string

客户端全局唯一的ID,需要用户自己生成,传入SDK。最大长度40个字符。

network

ip

string

调用方公网IP

location

latitude

string

调用方纬度信息,在需要客户端精确位置的业务场景提交

longitude

string

调用方经度信息,在需要客户端精确位置的业务场景提交

city_name

string

调用方所在城市,指明客户端粗略位置

biz_params

user_defined_params

object

其他需要透传给agent的参数

user_defined_tokens

object

透传agent所需鉴权信息

user_prompt_params

object

用于设置用户自定义prompt中的变量

user_query_params

object

用于设置用户自定义query中的变量

示例如下:

{
    "header": {
        "action":"run-task",
        "task_id": "9B32878******************3D053",
        "streaming":"duplex"
    },
    "payload": {
        "task_group":"aigc",
        "task":"multimodal-generation",
        "function":"generation",
        "model":"multimodal-dialog",
        "input":{
          "directive": "Start",
          "workspace_id": "llm-***********",
          "app_id": "****************"
        },
        "parameters":{
          "upstream":{
            "type": "AudioOnly",
            "mode": "duplex"
          },
          "downstream":{
            "voice": "longxiaochun_v2",
            "sample_rate": 24000
          },
          "client_info":{
            "user_id": "bin********207",
            "device":{
              "uuid": "432k*********k449"
            },
            "network":{
              "ip": "10.0.0.9"
            },
            "location":{
              "city_name": "北京市"
            }
          },
          "biz_params":{
            "user_defined_params": {
                "agent_id_xxxxx": {
                    "name": "value"
                }
            },
            "user_prompt_params": {
                "name": "value"
            },
            "user_query_params": {
                "name": "value"
            }
          }
        }
    }
}
IConversationCallback (回调接口)
    /**
     * 对话启动结果,鉴权、客户端加入通道成功后,会回调该消息
     */
    fun onStartResult(isSuccess: Boolean, errorInfo: TYError?)

    /**
     * 主动打断的回调,包括手动打断和语音打断
     */
    fun onInterruptResult(isSuccess: Boolean, errorInfo: TYError?)

    /**
     * 对话准备完成,多端(客户端/VoiceChat/视频理解)均加入通道后,会回调该消息,此时才能调用业务接口
     */
    fun onReadyToSpeech()

    /**
     * 状态切换回调
     * 包含DIALOG_IDLE,DIALOG_LISTENING,DIALOG_RESPONDING,DIALOG_THINKING
     */
    fun onConvStateChangedCallback(state: DialogState)

    /**
     * 音量强度回调
     * @param audioType 参考 {@link Constant.TYVolumeSourceType}
     * @param audioLevel 0-100
     */
    fun onConvSoundLevelCallback(audioLevel: Float, audioType: Constant.TYVolumeSourceType)

    /**
     * 超出用户有效输入超时时间的超时时间,收到此事件,用户需要重新启动或者结束对话
     * @param timeout 超时时间
     */
    fun onSpeechTimeout(timeout: Long)

    /**
     * 回路音频,用于客户端AEC回声消除
     * @param bytes 音频数据
     */
    fun onPlaybackAudioData(bytes: ByteArray)

    /**
     * 对话过程中的异常信息
     * @param errorInfo 异常信息
     */
    fun onErrorReceived(errorInfo: TYError)

    /**
     * 对话过程中的事件信息
     * @param errorInfo 事件信息
     */
    fun onConvEventCallback(var1: ConvEvent?)

    /**
     * 运行过程中回调关键日志信息给上层
     * @param level 日志级别,参考Android.Log
     * @param type 日志类型
     * @param debugInfo 日志信息
     */
    fun onDebugInfoTrack(level: Int, type: Constant.TYDebugInfoType, debugInfo: String)

onConvEventCallback AI对话 Response详情
  • EVENT_HUMAN_SPEAKING_DETAIL

    语音识别内容

    SpeechContent - response

    一级参数

    二级参数

    三级参数

    类型

    是否必选

    说明

    output

    event

    string

    事件名称:SpeechContent

    dialog_id

    string

    对话id

    text

    string

    用户语音识别出的文本,流式全量输出

    finished

    bool

    输出是否结束

    {
        "header": {
            "request_id": "9B32878******************3D053",
            "service_id": "368208df",
            "status_code": 200,
            "status_name": "Success",
            "status_message": "Success.",
            "attributes":{
              "user_id":"1234557879x"
            }
        },
        "payload": {
            "output":{
              "event": "SpeechContent",
              "dialog_id": "b39398c9dd8147********35cdea81f7",
              "text": "一二三",
              "finished": false
            },
            "usage":{
              "invoke":10,
              "model_x":10
            }
        }
    }
  • EVENT_RESPONDING_DETAIL

    大模型的返回文本

    output

    finished

    bool

    输出是否结束

    dialog_id

    string

    对话id

    event

    string

    消息类型

    text

    string

    LLM大模型返回的文本结果

    spoken

    string

    LLM大模型返回的播放内容的文本,可能跟 text 字段有所不同。

    extra_info

    object

    其他扩展信息,目前支持:

    commands: 命令字符串

    agent_info: 智能体信息

    tool_calls: 插件返回的信息

    dialog_debug: 对话debug信息

    timestamps: 链路中各节点时间戳

    示例:

    {
        "header": {
            "event":"result-generated",
            "task_id": "9B32878******************3D053"
        },
        "payload": {
            "output":{
              "event": "RequestAccepted",
              "dialog_id": "b39398c9dd8147********35cdea81f7",
              "text": "您输入了数字序列“12345”。如果您有关于这些数字的问题或者需要我用它们来完成某项任务,请告诉我更多的细节,我会尽力帮助您。",
              "spoken": "您输入了数字序列“12345”。如果您有关于这些数字的问题或者需要我用它们来完成某项任务,请告诉我更多的细节,我会尽力帮助您。",
              "finished": true,
            "extra_info": {
              "commands": "[{\"name\":\"VOLUME_SET\",\"params\":[{\"name\":\"series\",\"normValue\":\"70\",\"value\":\"70\"}]}]",
              "tool_result": [{
                "id": "",
                "type": "function",
                "function": {
                  "name": "function_name",
                  "arguments": "{\"id\": \"123\", \"name\": \"test\"}",
                  "outputs": "函数调用结果",
                  "status": {
                    "code": 200,
                    "message": "Success."
                  }
                }
              }]
            }
            },
            "usage":{
              "invoke":10,
              "model_x":10
            }
        }
    }

异常处理

onErrorReceived - response
百炼错误

错误码(Code)

错误信息(Message)

说明

403

AccessDenied.Unpurchased

Access to model denied. Please make sure you are eligible for using the model.

用户必须开通百炼服务

403

Model.AccessDenied

只支持从默认业务空间调用

ResponseTimeout

{"header":{"task_id":"899*******499","event":"task-failed","error_code":"ResponseTimeout","error_message":"Response timeout!","attributes":{}},"payload":{}}

百炼网关要求服务端和客户端必须持续通信,如果超过1分钟没有交互则会超时报错。

InternalError

{"header":{"task_id":"899*******499","event":"task-failed","error_code":"InternalError","error_message":"Internal server error!","attributes":{}},"payload":{}}

百炼网关要求服务端和客户端必须持续通信,如果超过1分钟没有交互则会超时报错。

多模态错误

(1)断连错误

出现以下错误时,错误码在headerstatus_code里,会话连接会断开,需要检查出错原因重新建连。

错误码(Code)

错误信息(Message)

说明

421

InvalidParameter

type of directive payload is error, please choose transcript or prompt

参数错误,RequestToRespond请求的参数type错误,只能支持以下两种:

(1)transcript 表示直接把文本转语音

(2)prompt 表示把文本送大模型回答

其他的参数错误 ,status_message 信息都有具体的提示说明。

422

DirectiveNotSupported

不支持的指令,请检查指令名称。

432

AppConfigError

获取到的百炼应用的配置有问题,参考status_message 里的具体信息修改。

433

BillingAuthError

未开通百炼多模态交互服务,或使用了错误账号。

444

ClientAudioTimeout

Waiting for client audio timed out.

服务端长时间收不到客户端的音频输入。

449

TooManyInterrupt

用户短时间内发送过多RequestToRespondRequestToSpeek 打断正常交互,通常是调用程序bug导致。

(2)普通错误

出现以下错误时,错误码在payloaderror_code里,连接不会断开,可以继续发送请求。

错误码(Code)

错误信息(Message)

说明

424

AudioFormatError

输入音频的格式不合规,ASR无法正常解析音频。

425

NoInputAudioError

没有获取到有效的输入音频数据,ASR无法识别。

426

InvalidTtsVoice

tts voice error , need cosyvoice-v2 voice.

参数错误,选择的音色不是cosyvoice-v2支持的音色。

(1)cosyvoice-v2支持的官方音色参考音色列表

(2)复刻音色,确认音色状态为“OK”后才能使用。查询指定音色

tts voice error , need qwen-tts-realtime voice.

参数错误,选择的音色不是qwen-tts-realtime支持的音色。

qwen-tts-realtime支持的官方音色参考实时语音合成-通义千问

451

NoSpeechRecognized

服务没有识别到用户讲话,通常是push2talk模式下,用户发送了SendSpeech后,没有说话就又发送了StopSpeech指令。其他模式下也有极少数情况是由背景噪音引起。

500

InternalSynthesizerError

Internal synthesizer error

tts问题,提供dialogIdvoicechat开发同学进行具体排查。

500

InternalAsrError

Internal asr error

asr问题,提供dialogIdvoicechat开发同学进行具体排查。

500

InternalLLMError

Internal LLM error

llm问题,提供dialogIdvoicechat开发同学进行具体排查。

500

LLMTimeoutError

LLM response timeout

llm问题,提供dialogIdvoicechat开发同学进行具体排查。

RTC连接错误码

错误码

错误名称

说明

1001

ERROR_CODE_AUTH_FAILED

RTC鉴权错误

1002

ERROR_CODE_JOIN_CHANNEL_FAILED

RTC加入channel出错

1003

ERROR_CODE_NETWORK_DISCONNECT

RTC网络断连

1004

ERROR_CODE_CHANNEL_ERROR

RTC连接错误

调用时序

全双工交互

image

半双工交互

image

更多SDK接口使用说明

双工交互

移动端Android SDK支持Duplex 双工交互模式。 在双工交互模式下,SDK支持在播放语音合成回复的同时,输入录音数据。当用户在此时说话时,服务会自动打断当前播报数据返回 (客户端播放器缓存需要应用层处理),并开始新的回复。

双工交互需要实现回声消除(AEC,Acoustic Echo Cancellation),Android SDK内置了回声消除算法。当您需要使用双工交互时,仍需要您进行必要的配置。

  • 输入麦克风录音音频

请将实时录音获取的音频数据通过如下接口传入SDK。

multiModalDialog.sendAudioData(data);
  • 输入参考通道音频

请将实时播放的音频数据通过如下接口传入SDK。注意传入数据需要保证与当前播放数据一致。

multiModalDialog.sendRefData(data);

VQA交互

VQA 是在对话过程中通过发送图片实现图片+语音的多模交互的功能。

核心过程是语音或者文本请求拍照意图触发"visual_qa"拍照指令。

当客户端通过回调函数onConvEventCallback收到拍照指令后, 发送图片链接或者base64数据(支持小于180KB的图片)。

  • 处理"visual_qa" command和上传拍照。

private void executeCmd(String cmd,String dialogId,String taskId){
  String cmdName = null;
  String cmdParamValue = null;
  try {
    cmdName = new JSONArray(cmd).getJSONObject(0).getString("name");
  }catch (Exception ex) {
    ex.printStackTrace();
  }
  switch (cmdName){
     case "visual_qa":
       JSONObject extraObject = new JSONObject();
       extraObject.put("images", imagesArray);
       multimodalConversation.requestToRespond(type, text, extraObject.toString());
       break:
  ......
}

//上传拍照
public static JSONArray getMockOSSImage() {
    JSONObject imageObject = new JSONObject();
    JSONArray images = new JSONArray();
    try{
      if (vqaUseUrl){
        imageObject.put("type", "url");
        imageObject.put("value", "https://help-static-aliyun-doc.aliyuncs.com/assets/img/zh-CN/7043267371/p909896.png");
      }else {
        imageObject.put("type", "base64");
        imageObject.put("value", getLocalImageBase64());
      }
      images.put(imageObject);

    }catch (Exception e){
      e.printStackTrace();
    }
    return images;
  }

通过 RTC 链路请求LiveAI

LiveAI (视频通话)是百炼多模交互提供的官方Agent。通过Android 全功能版本SDK, 您可以在应用中实现视频通话的功能。 本 SDK 内置了 RTC 协议,实现音视频双工的实时交互。

  • LiveAI调用时序

截屏2025-06-20 11

  • 关键代码示例

完整代码请参考 "前提条件" 章节下载的 Android Demo。

//1. 设置交互类型为AudioAndVideo
MultiModalRequestParam.UpStream.builder().mode("duplex").type("AudioAndVideo").build();

//2. 在建联后发送voicechat_video_channel 请求
private void startVideoMode() {
    if (isVideoMode) return;

    try {
        MultiModalRequestParam updateParams = MultiModalRequestParam.builder().build();
        JSONObject videoObj = new JSONObject();
        videoObj.put("action", "connect");
        videoObj.put("type", "voicechat_video_channel");

        List<JSONObject> videos = new ArrayList<>();
        videos.add(videoObj);

        updateParams.setBizParams(MultiModalRequestParam.BizParams.builder()
                .videos(videos).build());

        multiModalDialog.requestToRespond("prompt", "", updateParams.getParametersAsJson());
        multiModalDialog.setVideoContainer(videoContainer, uiHandler);

        isVideoMode = true;
        runOnUiThread(() -> videoContainer.setVisibility(View.VISIBLE));

    } catch (JSONException e) {
        Log.e(TAG, "启动视频模式失败", e);
    }
}

//3. 开始音视频交互。处理交互流程。注意 demo 中Constant.ChainMode.RTC 类型的处理。
private void handleOutputStarted() {
    if (!isRtcUseInternalAudio()) {
        audioPlayer.pause(true);
        audioPlayer.play();
    }
    if (authParams.getChainMode() == Constant.ChainMode.RTC) {
        //RTC 模式下,tts 合成数据速度为正常比例
        multiModalDialog.sendResponseStarted();
    }
}

private void handleOutputCompleted() {
    Log.d(TAG, "输出完成");
    if (authParams.getChainMode() != Constant.ChainMode.RTC) {
        multiModalDialog.sendResponseEnded();
        audioPlayer.isFinishSend(true);
    }
}

通过 Websocket 链路请求LiveAI

LiveAI (视频通话)是百炼多模交互提供的官方Agent。通过Android 全功能版本SDK, 您也可以在Websocket链路中通过自行录制视频帧的方式来调用视频通话功能。

注意:通过 Websocket 调用 LiveAI发送图片只支持base64编码,每张图片的大小在180K以下。

  • LiveAI调用时序

截屏2025-06-20 11

  • 关键代码示例

请注意参照如下的调用流程实现 通过Websocket 协议调用 LiveAI。

//1. 设置交互类型为AudioAndVideo
MultiModalRequestParam.UpStream.builder().mode("duplex").type("AudioAndVideo").build();

//2. 在建联后发送voicechat_video_channel 请求
private void startVideoMode() {
    if (isVideoMode) return;

    try {
        MultiModalRequestParam updateParams = MultiModalRequestParam.builder().build();
        JSONObject videoObj = new JSONObject();
        videoObj.put("action", "connect");
        videoObj.put("type", "voicechat_video_channel");

        List<JSONObject> videos = new ArrayList<>();
        videos.add(videoObj);

        updateParams.setBizParams(MultiModalRequestParam.BizParams.builder()
                .videos(videos).build());

        multiModalDialog.requestToRespond("prompt", "", updateParams.getParametersAsJson());
        multiModalDialog.setVideoContainer(videoContainer, uiHandler);

        isVideoMode = true;
        runOnUiThread(() -> videoContainer.setVisibility(View.VISIBLE));

    } catch (JSONException e) {
        Log.e(TAG, "启动视频模式失败", e);
    }
}

//3. 每 500ms 提交一张视频帧照片数据,注意图片尺寸小于 180KB。
/**
 * DEMO 流程未调用。演示在 websocket 链路中实现 liveAI
 * 启动视频帧流,每 500ms 发送一次图片帧
 */
private void startVideoFrameStreaming() {
    Thread videoStreamingThread = new Thread(() -> {
        try {
            while ( !Thread.currentThread().isInterrupted()) {
                Thread.sleep(500);

                JSONObject extraObject = new JSONObject();
                extraObject.put("images", getMockOSSImage());

                multiModalDialog.updateInfo(extraObject);
                }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (JSONException e) {
            throw new RuntimeException(e);
        }
    });

    videoStreamingThread.setDaemon(true);
    videoStreamingThread.setName("LiveAI-VideoStreaming");
    videoStreamingThread.start();

}

/**
 * build images list request
 * */
private static JSONArray getMockOSSImage() {
    JSONObject imageObject = new JSONObject();
    JSONArray images = new JSONArray();
    try{

        imageObject.put("type", "base64");
        imageObject.put("value", getLocalImageBase64());

        images.put(imageObject);

    }catch (Exception e){
        e.printStackTrace();
    }
    return images;
}

//read local image to base64
private static String getLocalImageBase64(){
    return "";
}

文本合成TTS

SDK支持通过文本直接请求服务端合成音频。

您需要在客户端处于Listening状态下发送requestToRespond请求。

若当前状态非Listening,需要先调用Interrupt 接口打断当前播报。

conversation.requestToRespond("transcript","幸福是一种技能,是你摒弃了外在多余欲望后的内心平和。",null);

自定义提示词变量和传值

  • 在管控台项目【提示词】配置自定义变量。

如下图示例,定义了一个user_name字段代表用户昵称。并将变量user_name以占位符形式${user_name} 插入到Prompt 中。

image.png

  • 在代码中设置变量。

如下示例,设置"user_name" = "大米"

//在请求参数构建中传入biz_params.user_prompt_params
HashMap<String, String> userPromptParams = new HashMap<>();
userPromptParams.put("user_name", "大米");
        MultiModalRequestParam.BizParams bizParams = MultiModalRequestParam.BizParams
                .builder()
                .userPromptParams(userPromptParams)
                .build();
  • 请求回复

image.png