更新时间:2026-04-10 GMT+08:00
分享

开发指导

该开发场景主要面向普通云手机客户端开发者,旨在帮助开发者通过集成和调用KooPhone端SDK的部分基本功能,初步理解和实现一个面向云手机用户的功能完善的H5客户端。

本章节所有开发示例均为展示基本功能的实现,仅供参考。

  1. 准备样式。

    绘制H5串流页面时,首先需要配置页面样式。主要分如下三类:

    1. 配置基础样式。

      准备html、body基础样式,支持全屏播放。

      <head>
          <style>
              html, body {
                  width: 100%;   /* 宽度占满整个浏览器窗口 */
                  height: 100%;  /* 高度占满整个浏览器窗口 */
              }
      
      
              body {
                  margin: 0;     /* 清除body默认的外边距(避免页面出现空白边) */
              }
          </style>
      </head>
    2. 配置容器布局样式。

      请参考以下配置div部分的CSS格式,铺满父元素并水平对齐子元素,两端各占30%,中间container固定为600px。以满足左侧(#left-box)输入鉴权信息及操作按钮,中间(#container)进行串流演示,右侧(#right-box)展示串流过程的信息。

      <head>
          <style>
              #box {
                  width: 100%;                /* 宽度占满父元素(这里是body,即全屏) */
                  height: 100%;               /* 高度占满父元素(全屏) */
                  display: flex;              /* 开启弹性布局,子元素会按flex规则排列 */
                  justify-content: space-between;  /* 子元素沿主轴(水平)两端对齐,中间自动填充空白 */
              }
      
              #left-box {
                  width:30%;		/* 宽度为父元素(#box)的30%(随窗口缩放变化) */
                  margin: 30px; 	/* 外边距30px(和其他元素拉开距离) */
              }
      
              #container {
                  width: 600px;  /* 固定宽度600像素(不会随窗口缩放变化) */
                  height: 100%;  /* 高度占满父元素(#box,即全屏) */
              }
      
              #right-box {
                  width: 30%;                /* 宽度为父元素(#box)的30%(随窗口缩放变化) */
                  height: 90%;               /* 高度为父元素的90%(留10%空白) */
                  overflow: auto;            /* 内容超出容器时,自动显示滚动条(只滚动内容,容器不撑大) */
                  border: solid 1px #000;    /* 黑色实线边框,宽度1px */
                  margin: 30px;              /* 外边距30px(和其他元素拉开距离) */
                  border-radius: 4px;        /* 边框圆角4px(让边角更圆润) */
              }
          </style>
      </head>
    1. 配置其他样式。

      请参考以下配置,进行输入框和按钮的配置。

      <head>
          <style>
              input {
                  width: 500px;       /* 输入框宽度500px(留边距) */
                  height: 30px;       /* 输入框高度30px */
                  margin-top: 20px;   /* 顶部外边距20px(和上方元素拉开距离) */
                  margin-bottom: 20px;/* 底部外边距20px(和下方元素拉开距离) */
              }
      
              button {
                  padding: 5px;  /* 按钮内部的内边距5px(让按钮文字和边框之间有空白,不会贴边) */
              }
          </style>
      </head>

  2. 准备Html页面元素。

    1. 准备输入框及按钮元素。

      请参考以下布局,设计IAM信息输入框,以及进入串流和结束串流按钮。

      <div id="box">
          <div id="left-box">
              <p style="color:red">输入以下参数,单击 初始化player并启动串流 按钮发起串流</p>
              <label for="">domain:</label>
              <input id="domain" type="text" value=""/><br>
              <label for="">user:</label>
              <input id="user" type="text" value=""/><br>
              <label for="">password:</label>
              <input id="password" type="password" value=""/><br>
              <label for="">instance_id:</label>
              <input id="instance_id" type="text" value=""/><br>
              <br>
              <button onclick="enter()">初始化player并启动串流</button>
              <br>
              <button onclick="closeMediaStream()">退出串流</button>
              <br>
          </div>
          <div id="container"></div>
          <div id="right-box"></div>
      </div>
    2. 引入SDK。
      • 纯浏览器环境,适用于不使用构建工具(如Webpack/Vite),仅通过浏览器原生支持的ES8模块开发场景。
        <script type="text/javascript" src="./js/kp-client-xx.js"></script>
        <script type="text/javascript">
            var client = new KPClient();
        </script>
      • 工程化项目,适用于使用构建工具的项目,模块化语法会被构建工具处理,无需依赖浏览器原生支持。
        import { KPClient } from './js/kp-client-xx.js';
        const client = new KPClient();

  3. 自动获取鉴权信息。

    快速开始中提供了手动获取鉴权信息进入串流的方案。这里给出自动获取鉴权并进入串流的使用指导,方便用户直接进行工程化部署。

    1. 部署本地Proxy。
      1. 在串流时,由于浏览器跨域问题,无法在js中直接请求鉴权接口,因此需要在本地启动代理服务。将以下代码保存到本地proxy.js文件中。
        const http = require('http');
        const { URL } = require('url');
        const { createServer: createProxyServer } = require('http-proxy');
        
        
        // 读取命令行参数:node proxy.js url1 url2
        const args = process.argv.slice(2);
        if (args.length < 2) {
            process.exit(1);
        }
        
        
        const TARGET_AUTH = args[0];
        const TARGET_TOKEN = args[1];
        const PORT = 8080;
        
        
        // 创建代理服务
        const proxyAuth = createProxyServer({ target: TARGET_AUTH, changeOrigin: true });
        const proxyToken = createProxyServer({ target: TARGET_TOKEN, changeOrigin: true });
        
        
        // 创建本地HTTP服务
        const server = http.createServer((req, res) => {
            const path = req.url;
        
        
            res.setHeader("Access-Control-Allow-Origin", "*");
            res.setHeader("Access-Control-Allow-Headers", "*");
            res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
            res.setHeader('Access-Control-Expose-Headers', 'x-subject-token');
        
        
            if (req.method === 'OPTIONS') {
                res.writeHead(204);
                res.end();
                return;
            }
        
        
            if (path === '/v3/auth/tokens') {
                proxyToken.web(req, res);
            } else {
                proxyAuth.web(req, res);
            }
        });
        
        
        // 启动服务
        server.listen(PORT, () => {
            console.log('跨域代理服务已启动');
            console.log(`本地地址: http://localhost:${PORT}`);
        });
      2. 准备请求串流鉴权的URL地址和请求IAM Token的URL地址。
        • 请求串流鉴权的URL地址,在API Explorer中获取。举例:如果是北京4区域,地址为https://koophone.myhuaweicloud.com。
        • 请求IAM Token的URL地址,在构造IAM请求中获取。举例:如果是北京4区域,地址为https://iam.cn-north-4.myhuaweicloud.com
      3. 启动本地代理。
        1. 安装依赖包npm install http-proxy。
        2. 在命令行窗口(如CMD/Terminal控制台等)中,通过cd命令切换至proxy.js文件所在目录。执行以下命令切换 :
          node proxy.js https://koophone.***.com https://iam.***.com

          上述命令中的***需替换为3.a.ii中获取的串流鉴权的URL地址和请求IAM Token的URL地址。

          执行结束后,如果启动成功,如图1所示。

          图1 启动本地代理
    2. 获取IAM Token。

      在获取KooPhone鉴权信息之前,需要准备本账号的IAM相关信息:

      • IAM用户所属账号名称(domain)
      • IAM用户名(user)
      • IAM用户登录密码(password)
      • KooPhone云手机实例ID(instance_id)

      将IAM信息和实例信息替换到如下代码中的参数定义部分,然后使用如下refreshIamToken函数即可获取到IAM Token。

      // IAM信息填充
      const domain = document.getElementById("domain").value;
      const user = document.getElementById("user").value;
      const password = document.getElementById("password").value;
      const instanceId = document.getElementById("instance_id").value;
      
      
      async function refreshIamToken() {
          return fetch("http://localhost:8080/v3/auth/tokens",
                       {
              method: "POST",
              headers: {
                  "Content-Type": "application/json",
              },
              body: JSON.stringify({
                  "auth": {
                      "identity": {
                          "methods": [
                              "password"
                          ],
                          "password": {
                              "user": {
                                  "domain": {
                                      "name": domain
                                  },
                                  "name": user,
                                  "password": password
                              }
                          }
                      },
                      "scope": {
                          "domain": {
                              "name": domain
                          }
                      }
                  }
              }),
              mode: "cors"
          })
              .then(response  => {
              const headers = response.headers;
              for (let [key, value] of headers.entries()) {
                  console.log(`${key}: ${value}`);
              }
              return headers.get('x-subject-token');
          });
      }
    3. 获取串流鉴权信息。

      获取IAM Token后,即可请求KooPhone实例串流鉴权信息。准备KooPhone云手机实例ID(instance_id),将实例ID替换如下instanceId参数。

      // 串流实例信息填充
      const instanceId = document.getElementById("instance_id").value;
      
      
      async function refreshDeviceToken() {
          const token = await refreshIamToken();
          return fetch(`http://localhost:8080/v1/instances/${instanceId}/auth`,
                       {
              method: "POST",
              headers: {
                  "Content-Type": "application/json",
                  "x-auth-token": token,
                  "x-user-id": "123456",
                  "x-request-id": "0000123456"
              },
              mode: "cors"
          })
              .then(resp => resp.text())
              .then(data => {
              let json = JSON.parse(data);
              if (json["error_code"] === "0") {
                  let deviceToken = json["data"]["device_token"];
                  let deviceId = json["data"]["resource"]["device_id"];
                  let signalUrl = json["data"]["resource"]["rtc"]["ice_signaling"]["signaling_url"]
                  return {deviceToken, deviceId, signalUrl};
              } else {
                  // 请求异常
                  alert(json["error_msg"]);
              }
          });
      }

  4. 初始化SDK并启动串流。

    在完成步骤1~3后,已经准备好初始化所需的元素mountPoint(串流云机所需的挂载点,String或HTMLElement类型,且tagName必须是div)。

    如果对串流有其他要求(比如音量,视频宽高等),可以按照JS SDK参考准备其他参数。

    1. 初始化player。
      // 创建时,配置选项
      let player = CloudappClient.createCloudappPlayer({
          mountPoint: 'container'
          muted: false,
          volume: 0.5,
          frameAspect: '16:9',
          noOperationThreshold: 120,
          countdownTime: 60,
          sessionKeepingTime: 60,
          enableClipboard: true
      });
      if (!player) {
      	console.log('Player创建失败!');
      }
    2. 启动串流。

      在获取到实例串流信息,并初始化player之后,即可开始串流。

      1. 检查浏览器支持情况。
        player.isBrowserSupport()

        目前暂不支持UC浏览器和MacOS/iPad原生浏览器。如果浏览器无法使用,建议使用Chrome浏览器。

      2. 设置所需回调。
        // 举例1:设置状态变化回调
        player.on("onStateChange", function (event) {
            console.log("onStateChange:" + event.state);
        });
        // 举例2:设置用户动作回调
        player.on("onUserAction", function (event) {
            console.log("useraction:" + event.action);
        });
      3. 启动串流。
        // 获取输入框参数
        const {deviceToken, deviceId, signalUrl} = await refreshDeviceToken();
        // 启动串流
        player.initMediaStream({
            boxid: deviceId, // 设备ID
            token: deviceToken, // 鉴权Token
            uuid: 'test-user-id', // 串流用户ID
            signaling_url: signalUrl // 信令服务器地址
        });
        在浏览器中单击“初始化player并启动串流”,可以看到云机画面。
        图2 初始化player并启动串流
      4. 退出串流。
        player.closeMediaStream();

        在浏览器中单击“退出串流”,关闭云机画面。

        图3 退出串流

(可选)设置音频、视频

音频

  • 设置音量

    绘制音量输入框,设置音量按钮。

    <input id="volume" type="text" name="name"/><br>
    <button onclick="setVolume()">设置音量</button><br>

    实现音量设置函数。

    function setVolume() {
        let volume = Number(document.getElementById("volume").value);
        player.setVolume(volume);
    }
  • 设置静音

    绘制静音选择框,选择后单击设置player静音开关按钮。

    <div>
        <label for="">是</label>
        <input type="radio" name="muted" style="width:20px;height:20px;" value="1" checked="true"/>
        <label for="">否</label>
        <input type="radio" name="muted" style="width:20px;height:20px;" value="0"/>
    </div>
    <button onclick="setMuted()">设置player静音开关</button><br>

    实现静音设置函数。

    function setMuted() {
        let radios = document.getElementsByName('muted');
        let value;
        for(let i = 0; i < radios.length; i++) {
            if(radios[i].checked) {
                value = radios[i].value;
                break;
            }
        }
        if (value === '1') {
                player.setMuted(true);
            } else {
                player.setMuted(false);
        }
    }

视频

  • 设置视频清晰度

    绘制视频质量输入框,设置视频质量按钮。输入值参考SDK中的setVideoQuality()函数说明。

    <input id="quality" type="text" name="name"/><br>
    <button onclick="setQuality()">设置画质</button><br>

    实现视频清晰度设置按钮。

    function setQuality() {
        let quality = Number(document.getElementById("quality").value);
        player.setVideoQuality(quality);
    }
  • 全屏及退出播放

    绘制全屏及退出全屏按钮。

    <button onclick="setMediaFullScreen()">设置player全屏播放</button><br>
    <button onclick="setMediaExitFullScreen()">退出player全屏播放</button><br>

    实现全屏及退出播放按钮对应功能函数。

    function setMediaFullScreen() {
    	player.setMediaFullScreen();
    }
    
    
    function setMediaExitFullScreen() {
    	player.setMediaExitFullScreen();
    }

相关文档