# 硅基DUIX H5 SDK使用文档

# 安装

npm i duix-guiji-light -S

# 快速开始


import DUIX from 'duix-guiji-light'

const duix = new DUIX()

duix.on('intialSucccess', () => {
  // 开始会话
  duix.start({
    openAsr: true
  }).then(res => {
    console.info(res)
  })
})

// 初始化
duix.init({
  conversationId: '',
  sign: 'xxxx',
  containerLable: '.remote-container'
})

注意: 不要将duix实例放在Vue的data中,也不要放在react的state中(无需使其响应式)。

# 调用流程

h5sdk.jpg

# 方法

# init(option: object): Promise

duix.init({
  sign: '',
  containerLable: '.remote-container',
  conversationId: '',       
})

参数

名称 类型 必填 描述
containerLable string 数字人容器。数字人将渲染到这个Dom中。
sign string 鉴权字符串。如何获取sign? (opens new window)
conversationId number 平台会话id

# start(option:object): Promise

调用 start 方法将开始渲染数字人并进行交互。

注意: 此方法需要在intialSucccess事件触发后调用,intialSucccess事件表示所有资源准备完成。如下:

duix.on('intialSucccess', () => {
  duix.start({
     muted: true,
     wipeGreen: false,
 }).then(res => {
    console.log('res', res)
 })
})

参数

key 类型 必填 默认值 说明
muted boolean false 是否以静音的模式开启数字人视频。
重要提示: 由于自动播放政策 (opens new window)限制,如果您的网页还没有与用户有任何点击交互,请把这个参数置为true否则将导致数字人无法加载。如果您有这样的需求,建议您先用静音模式启动,在产品中设计一个交互,比如一个“开始”的按钮来调用duix.setVideoMuted(false)
openAsr boolean false 是否直接开启实时识别,此项传true,相当于在调start后立即调用 openAsr 方法
wipeGreen boolean false 是否对视频做扣绿幕操作。在平台上创建会话时需上传一个纯绿色的背景图片
userId number 用户唯一标识

# setVideoMuted(flag:boolean)

设置数字人视频是否静音, true是静音,false为非静音。

# break()

打断数字人说话

# speak(option: Object): Promise

驱动数字人说话,支持文本驱动和音频文件驱动。

duix.speak({content: '', audio: 'https://your.website.com/xxx/x.wav'})

参数

名称 类型 必填 描述
content string 数字人回答的文本
audio string 数字人回答音频地址,可以通过getAnswer获取平台配置的答案
interrupt boolean 是否打断之前说的话

# answer(option: Object): Promise

数字人回答问题

duix.answer({question: 'xxx'})

参数

名称 类型 必填 描述
question string 问题文本
interrupt boolean 是否打断之前说的话

# getAnswer(option: Object): Promise

平台获取问题的答案

duix.getAnswer({ question: '今天的天气怎么样?' })

参数

名称 类型 必填 描述
question string 问题文本
userId number 业务侧用户唯一id,指定后获得答案是开启记忆功能

返回data

名称 类型 描述
answer string 数字人回答的文本
audio string 数字人回答音频地址

# startRecord():Promise

开始录音。返回当前录音的MediaStrem,可用来显示声波动画。

# stopRecord():Promise

结束录音

# openAsr():Promise

开启语音实时识别(注意此方法需在show触发时候调用)。开启语音实时识别后,可通过监听 asrResult 事件,接收识别(文本)结果。

# closeAsr():Promise

关闭语音实时识别。

# stop()

停止当前会话。建议在页卸载事件中调用此方法,以防止刷新或关闭网页时当前会话资源未及时释放。

window.addEventListener('beforeunload', function(event) {
  if (duix) {
    duix.stop()
  }
});

# getLocalStream()

获取本地语音流,方便外部做音频可视化等功能

# getRemoteStream()

获取远端音视频流,方便外部做自定义

# resume()

恢复播放,目前仅针对部分移动端浏览器即便由用户操作触发自动播放,仍无效的情况。在抛出4009的error中由用户操作触发resume方法可解决。

# on(eventname, callback)

监听事件。

# 参数
# eventname

事件名称,详见下方表格。

# callback

回调函数

# 返回格式说明

对于返回Promise的方法,参数格式为{ err, data },如果err不为空,则代表调用失败。

# 事件

名称 描述
error 有未捕获错误时触发。
bye 会话结束时触发。
intialSucccess 数字人初始化成功。可以在这个事件的回调中调用start方法
show 出数字人已显示。
progress 数字人加载进度。
speakSection 数字人说话当前的音频和文本片段(answer方法会采用流式获取结果,如果单独调用speak,该事件与speakStart一致)
speakStart 驱动数字人说话,到数字人实际说话之间有一点延迟,此事件表示数字人实际开始说话了
speakEnd 数字人说话结束
asrStart 单句语音识别开启。 startRecord时只会触发一次
asrData 单句语音实时识别结果。startRecord时会增加返回所有识别结果的数组textList
asrStop 单句语音识别结束
report 每秒报告RTC网络/画面质量等信息

# error

{
  code: '', // 错误码  
  message: '', // 错误信息
  data: {} // 错误内容
}

error code

名称 描述 data
3001 RIC连接失败
4001 开始会话失败
4005 鉴权失败
4007 服务端会话异常结束 code: 100305 模型文件未找到
4008 获取麦克风流失败
4009 浏览器基于播放策略无法自动播放 请先考虑静音播放或用户操作调用start方法

# progress

number类型的进度,0-100

# speakSection


{
  audio: '', // 音频地址
  content: '', // 文本内容
}

# speakStart


{
  audio: '', // 音频地址
  content: '', // 文本内容
}

# speakEnd


{
  audio: '', // 音频地址
  content: '', // 文本内容
}

# asrData

每段文本的识别,会以一个asrStart开始,一个asrStop结束,中间有一个或多个asrData(递增式的推送),可以在asrData事件中,获取语音识别结果,用于展示。


{
  content: '', // 文本内容
}

# report

{
    "video": { // 视频相关信息
        "download": {
            "frameWidth": 1920, // 分辨率-宽
            "frameHeight": 1080,// 分辨率-高
            "framesPerSecond": 24,// 分辨率-帧率
            "packetsLost": 0, // 总丢包数
            "packetsLostPerSecond": 0 // 总丢率(每秒丢包数)
        }
    },
    "connection": { // 连接信息
        "bytesSent": 206482, // 发送总字节数
        "bytesReceived": 79179770, // 接收总字节数
        "currentRoundTripTime": 3, // 包往返时间(单位毫秒),这个时间越大画面越延迟
        "timestamp": 1688043940523,
        "receivedBitsPerSecond": 2978472, // 接收码率(每秒接收到的bit数,1Mb = 1024^2 bit)
        "sentBitsPerSecond": 7920 // 发送码率(每秒发送的bit数,1Mb = 1024^2 bit)
    }
}

注意: 未在上述详细列出的事件参数均为空

# 代码示例

<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
  <meta http-equiv="Pragma" content="no-cache" />
  <meta http-equiv="expires" content="0" />
  <meta name="viewport" content="width=device-width,initial-scale=1.0,maximu-scale=1.0,user-scalable=no" />
  <title>Duix Sdk Simple Example</title>
  <style>
    html,
    body {
      margin: 0;
      padding: 0;
    }

    .modal {
      position: fixed;
      left: 0;
      top: 0;
      width: 100vw;
      height: 100vh;
      overflow: auto;
      background-color: rgba(0, 0, 0, 0.4);
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .modal-content {
      background-color: #fefefe;
      padding: 20px;
      border: 1px solid #888;
      width: 80%;
      max-width: 600px;
      border-radius: 4px;
    }

    .container {
      width: 100vw;
      height: 100vh;
    }

    .item {
      margin-bottom: 10px;
      display: flex;
      align-items: center;
      justify-content: center;
    }

    .item>div {
      margin-bottom: 10px;
      gap: 10px;
    }

    .item>span {
      font-size: 18px;
      font-weight: bold;
      margin-bottom: 10px;
    }

    .input {
      background: #F2F3F5;
      height: 40px;
      line-height: 40px;
      border: none;
      outline: none;
      border-radius: 2px;
      padding: 0 8px;
      width: 100%;
      box-sizing: border-box;
    }

    .btn {
      border: none;
      border-radius: 4px;
      width: 100%;
      height: 40px;
      background: #166AFF;
      color: #fff;
      cursor: pointer;
      margin-top: 20px;
    }
    .subtitle {
      position: absolute;
      bottom: 40px;
      left: 50%;
      transform: translate(-50%);
      color: #000;
      padding: 12px;
      box-sizing: border-box;
      text-align: center;
      background-color: rgba(255,255, 255, 0.5);
      border-radius: 12px;
      visibility: hidden;
    }
    .subtitle:empty {
      display: none;
    }
  </style>
  <script src="https://cdn.guiji.ai/duix/sdk/0.0.1/duix.js"></script>
</head>

<body>
  <!-- 数字人容器 -->
  <div class="container"></div>
  <div class="subtitle"></div>
  <div id="modal" class="modal">
    <div class="modal-content">
      <div class="item">
        <span>会话演示DEMO</span>
      </div>
      <div class="item">
        <input class="input" id="sign" placeholder="请输入sign" value="" />
      </div>
      <div class="item">
        <input class="input" id="conversationId" placeholder="请输入会话Id" value="" />
      </div>
      <div class="item">
        <button id="start" onclick="init()" class="btn">开始会话</button>
      </div>
    </div>
  </div>
  <script>
    // 演示用的duix.js未必是最新的,请通过npm安装最新sdk
    const duix = new window.DUIX()
    function init() {
      const sign = document.querySelector('#sign').value // sign由服务端生成
      const conversationId = document.querySelector('#conversationId').value // duix平台会话id
      if (!sign || !conversationId) {
        return alert('参数不能为空')
      }
      duix.on('error', data => {
        console.error(data)
      })
      duix.on('intialSucccess', () => {
        console.info('intialSucccess')
        // 此时初始化成功,可调用start
        // 部分浏览器,特别是移动端浏览器,播放数字人需要由用户操作触发,推荐start事件由用户点击调用,哪怕muted是静音状态,否则部分浏览器可能不显示数字人
        duix.start({ openAsr: true }).then(res => {
          console.info('start', res)
        })
      })
      duix.on('bye', (data) => {
        console.info('bye', data)
      })
      duix.on('progress', progress => {
        console.info('progress', progress)
      })
      duix.on('show', () => {
        console.info('show')
        // 此时可确认视频已播放
        document.querySelector('#modal').style.display = "none"
        document.querySelector('.subtitle').style.visibility = "visible"
      })
      duix.on('openAsrSuccess', () => {
        console.info('openAsrSuccess')
      })
      duix.on('asrStart', (data) => {
        console.info('asrStart', data)
        document.querySelector('.subtitle').innerText = ''
      })
      duix.on('asrData', (data) => {
        console.info('asrData', data)
      })
      duix.on('asrStop', (data) => {
        console.info('asrStop', data)
      })
      duix.on('speakStart', (data) => {
        console.info('speakStart', data)
      })
      duix.on('speakEnd', (data) => {
        console.info('speakEnd', data)
      })
      duix.on('speakSection', (data) => {
        console.info('speakSection', data)
        document.querySelector('.subtitle').innerText = data.text
      })
      duix.on('speakError', (data) => {
        console.info('speakError', data)
      })


      duix.init({
        sign,
        containerLable: '.container',
        conversationId: conversationId,
      }).then(data => {
        console.info('init', data)
      })
    }

  </script>
</body>

</html>

# 常见问题

  1. 部分浏览器,特别是移动端浏览器,播放数字人需要由用户操作触发,推荐start事件由用户点击调用,哪怕muted是静音状态,否则部分浏览器可能不显示数字人
  2. 部分ios系统下的微信浏览器需要调用navigator.mediaDevices.getUserMedia授权后才能播放远端流
  3. 如果是开启asr识别的情况下,会需要getUserMedia的用户授权,由于浏览器限制,此时本地调试需要https的环境。
  4. 微信小程序对接的方式,可以通过web-view组件对接。
  5. 部分移动端浏览器即便由用户点击调用start开启,仍无法适应浏览器的自动播放策略,可在收到4009的error时,再由用户事件触发resume方法
  6. 如果需要使用开场白、唤醒词、打断词等配置,可通过openapi——获取会话详情接口取得,SDK本身不提供业务逻辑。
  7. 部分浏览器不支持RTC,目前验证不支持的有小米浏览器。
  8. 由于webrtc不支持http协议,不支持ip地址访问,请使用https及域名访问。

# 版本记录

0.0.1 1.初始化sdk

0.1.0 1.增加startRecord和stopRecord录音功能