腾讯实时音视频(TRTC)研究技术文档

腾讯实时音视频(TRTC)研究技术文档

  • 整体流程
  • 用户同步
  • 签名调用:
  • 返回类封装
  • 前端测试代码
  • 总结

整体流程

腾讯实时音视频(TRTC)研究技术文档_第1张图片
根据业务逻辑在service里签名传到前台,前台根据userId,和签名,房间号(房间号后台管理,每进入房间默认创建房间号,返回前端)进入房间,然后根据前台操作开启视频直播,此房间号后台记录后广播到用户展示的房间列表,其他用户通过点击房间号,进入各个房间,根据操作开启关闭摄像头通讯。

用户同步

2 .0 接口调用说明

2.1 请求URL

https://console.tim.qq.com/v4/im_open_login_svc/account_import?usersig=xxx&identifier=admin&sdkappid=88888888&random=99999999&contenttype=json

2.2 请求参数

URL中各参数的含义以及填写方式参见REST API简介。

2.3 最高调用频率

100次/秒。如需提升调用频率,请根据工单模板提交工单申请处理。

2.4 HTTP请求方式

POST

2.5 HTTP请求包体格式

JSON

2.6 请求包示例

{
     
   "Identifier":"test",
   "Nick":"test",
   "FaceUrl":"http://www.qq.com"
}

2.7 请求包字段说明

字段 类型 属性 说明
Identifier String 必填 用户名,长度不超过 32 字节
Nick String 选填 用户昵称
FaceUrl String 选填 用户昵称
Type Integer 选填 帐号类型,开发者默认无需填写,值0表示普通帐号,1表示机器人帐号。

2.8 应答包体示例

{
     
   "ActionStatus":"OK",
   "ErrorInfo":"",
   "ErrorCode":0
}

2.9 应答包字段说明

字段 类型 说明
ActionStatus String 请求处理的结果,OK表示处理成功,FAIL表示失败。
ErrorCode Integer 错误码。
ErrorInfo String 错误信息。

签名调用:


package com.example.demo.utils.tls_sigature;

import com.example.demo.utils.base64_url.base64_url;
import com.example.demo.utils.tls_dto.GenTLSSignatureResult;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.json.JSONObject;

import java.io.CharArrayReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.util.Arrays;
import java.util.zip.Deflater;

/**
 * Created by liwenbin on 2018/9/17.
 */
public class Sigature {
     
    /**
     * @brief 生成 tls 票据,精简参数列表
     * @param skdAppid 应用的 sdkappid
     * @param identifier 用户 id
     * @param privStr 私钥文件内容
     * @param expire 有效期,以秒为单位,推荐时长一个月
     * @return
     * @throws IOException
     */
    public static GenTLSSignatureResult GenTLSSignatureEx(
            long skdAppid,
            String identifier,
            String privStr,
            long expire) throws IOException {
     

        GenTLSSignatureResult result = new GenTLSSignatureResult();

        Security.addProvider(new BouncyCastleProvider());
        Reader reader = new CharArrayReader(privStr.toCharArray());
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter();
        PEMParser parser = new PEMParser(reader);
        Object obj = parser.readObject();
        parser.close();
        PrivateKey privKeyStruct = converter.getPrivateKey((PrivateKeyInfo) obj);

        String jsonString = "{"
                + "\"TLS.account_type\":\"" + 0 +"\","
                +"\"TLS.identifier\":\"" + identifier +"\","
                +"\"TLS.appid_at_3rd\":\"" + 0 +"\","
                +"\"TLS.sdk_appid\":\"" + skdAppid +"\","
                +"\"TLS.expire_after\":\"" + expire +"\","
                +"\"TLS.version\": \"201512300000\""
                +"}";

        String time = String.valueOf(System.currentTimeMillis()/1000);
        String SerialString =
                "TLS.appid_at_3rd:" + 0 + "\n" +
                        "TLS.account_type:" + 0 + "\n" +
                        "TLS.identifier:" + identifier + "\n" +
                        "TLS.sdk_appid:" + skdAppid + "\n" +
                        "TLS.time:" + time + "\n" +
                        "TLS.expire_after:" + expire +"\n";

        try {
     
            //Create Signature by SerialString
            Signature signature = Signature.getInstance("SHA256withECDSA", "BC");
            signature.initSign(privKeyStruct);
            signature.update(SerialString.getBytes(Charset.forName("UTF-8")));
            byte[] signatureBytes = signature.sign();

            String sigTLS = Base64.encodeBase64String(signatureBytes);

            //Add TlsSig to jsonString
            JSONObject jsonObject= new JSONObject(jsonString);
            jsonObject.put("TLS.sig", (Object)sigTLS);
            jsonObject.put("TLS.time", (Object)time);
            jsonString = jsonObject.toString();

            //compression
            Deflater compresser = new Deflater();
            compresser.setInput(jsonString.getBytes(Charset.forName("UTF-8")));

            compresser.finish();
            byte [] compressBytes = new byte [512];
            int compressBytesLength = compresser.deflate(compressBytes);
            compresser.end();
            String userSig = new String(base64_url.base64EncodeUrl(Arrays.copyOfRange(compressBytes,0,compressBytesLength)));

            result.urlSig = userSig;
        }
        catch(Exception e)
        {
     
            e.printStackTrace();
            result.errMessage = "generate usersig failed";
        }

        return result;
    }
}

返回类封装


package com.example.demo.utils.tls_dto;

/**
 * Created by liwenbin on 2018/9/17.
 */
public class GenTLSSignatureResult {
     
    //错误信息
    public String errMessage;
    //签名
    public String urlSig;
    public int expireTime;
    public int initTime;

    public String getErrMessage() {
     
        return errMessage;
    }

    public void setErrMessage(String errMessage) {
     
        this.errMessage = errMessage;
    }

    public String getUrlSig() {
     
        return urlSig;
    }

    public void setUrlSig(String urlSig) {
     
        this.urlSig = urlSig;
    }

    public int getExpireTime() {
     
        return expireTime;
    }

    public void setExpireTime(int expireTime) {
     
        this.expireTime = expireTime;
    }

    public int getInitTime() {
     
        return initTime;
    }

    public void setInitTime(int initTime) {
     
        this.initTime = initTime;
    }
}

前端测试代码

客户一:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试title>
head>
<body >


<video id="localVideo" muted autoplay playsinline>video>

<video id="remoteVideo" autoplay playsinline>video>







<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js">script>
<script src="https://sqimg.qq.com/expert_qq/webrtc/3.0/WebRTCAPI.min.js">script>
<script>
    //调试模式
    var RTC = new WebRTCAPI( {
      
        "userId": "sootower",
        "sdkAppId":  1400134005,
        "userSig": "eJxFkF1vgjAUhv8Lt1uWlloMuyOoodlQh7gEb5qOFuyEtkL92Jb991Wm8ebk5Hly8ua8P17*unpixkhOmaWo496zB7zHAYuzkZ2grLKic9jHoQ-ATR5F10utLhxADH0EwF1KLpSVlRzueq2tPrn13-WydjCdFjF5iyMe1knOkzrOyNyocfOSrILZUS2-dQpFThpQ6E62abM4kW205G02*fxA5cGgAodRsN8tZuspO6Nqv8m27Xvsbx5yMsf9*hbGd3T4zkXCEQAQuYGv0spWXDhGYxhgMAqunJWlPihL7ZcRQx2-fwBhWS0_",
        "debug":{
      
            "log": true, //是否在控制台打印调试日志 ,默认为false
            "vconsole": true, //是否展示 vconsole (方便在移动端查看日志)
            "uploadLog": true //是否上报日志
        }
    } );

    RTC.getLocalStream({
      
        video:true,
        audio:true,
        attributes:{
      
            width:640,
            height:480,
            frameRate:20
        }
    },function( info ){
      
        // info { stream }
        var stream = info.stream;
        document.getElementById("localVideo").srcObject = stream

        RTC.enterRoom( {
      
            roomid : 123456,
            role: 'user'
            // privateMapKey: "xxxxxxxxxxxxx" //不必须
        }, function(){
      
            //进房房间成功
            console.info( "==进入房间成功==" )
            RTC.startRTC({
      
                role: 'user',
                stream: stream
            }, function(){
      
                console.info( "==开始推流==" )
                //成功
            },function(){
      
                console.info( "==推流失败==" )
                //失败
            });
        } ,  function(data){
      
            console.info( "==进入房间失败==" )
            //进入房间失败
        } );
    },function ( error ){
      
        console.error( error )
    });

    RTC.on( 'onRemoteStreamUpdate' , function( data ){
      
        if( data && data.stream){
      
            var stream1 = data.stream
            console.debug( data.userId + 'enter this room with unique videoId '+ data.videoId  )
            document.querySelector("#remoteVideo").srcObject = stream1
//            document.getElementById("localVideo").srcObject = stream
//            RTC.updateStream({
      
//                role: "user",
//                stream: stream
//            }, function(){
      
//                console.debug('updateStream succ')
//            }, function(){
      
//                console.debug('updateStream failed')
//            });
        }else{
      
            console.debug( 'somebody enter this room without stream' )
        }
    })


script>
body>
html>

客户二:


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>标题title>
head>
<body >


<video id="localVideo" muted autoplay playsinline>video>

<video id="remoteVideo" autoplay playsinline>video>







<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js">script>
<script src="https://sqimg.qq.com/expert_qq/webrtc/3.0/WebRTCAPI.min.js">script>
<script>

    //调试模式
    var RTC = new WebRTCAPI( {
      
        "userId": "liwenbin",
        "sdkAppId":  1400134005,
        "userSig": "eJxFkF1PgzAUhv8Ltxhp6Sqbd06aCPNjuGUKN02hnZwIpYG6yYz-XUZYvDkXz5M3b97z42wfN9fCGJBcWE5a6dw6yLkasfo20Cou9la1A-bpwkfoIg*q7aDRZ44wxT5B6F*CVNrCHsZcBUelc9CT6*BjgE8svY*SsKEbGr95D7UqA5uxU3gQxF3jfk1e4z7GK-c9ZC-ecrvaJVF59zzPauMtWZJSM8vBREnVz4*4ZK5X4DyvK*i6LE3lDhaXMvnJx3VDJZ4hhMlw6CQt1OrMKQnwDUV*MHFRFM2Xttz2Ro3v*P0DHgVXxg__",
        "debug":{
      
            "log": true, //是否在控制台打印调试日志 ,默认为false
            "vconsole": true, //是否展示 vconsole (方便在移动端查看日志)
            "uploadLog": true //是否上报日志
        }
    } );

    RTC.getLocalStream({
      
        video:true,
        audio:true,
        attributes:{
      
            width:640,
            height:480,
            frameRate:20
        }
    },function( info ){
      
        // info { stream }
        var stream = info.stream;
        document.getElementById("localVideo").srcObject = stream

        RTC.enterRoom( {
      
            roomid : 123456,
            role: 'user'
            // privateMapKey: "xxxxxxxxxxxxx" //不必须
        }, function(){
      
            //进房房间成功
            console.info( "==进入房间成功==" )
            RTC.startRTC({
      
                role: 'user',
                stream: stream
            }, function(){
      
                console.info( "==开始推流==" )
                //成功
            },function(){
      
                console.info( "==推流失败==" )
                //失败
            });
        } ,  function(data){
      
            console.info( "==进入房间失败==" )
            //进入房间失败
        } );
    },function ( error ){
      
        console.error( error )
    });

    RTC.on( 'onRemoteStreamUpdate' , function( data ){
      
        if( data && data.stream){
      
            var stream1 = data.stream
            console.debug( data.userId + 'enter this room with unique videoId '+ data.videoId  )
            document.querySelector("#remoteVideo").srcObject = stream1
//            document.getElementById("localVideo").srcObject = stream
//            RTC.updateStream({
      
//                role: "user",
//                stream: stream
//            }, function(){
      
//                console.debug('updateStream succ')
//            }, function(){
      
//                console.debug('updateStream failed')
//            });
        }else{
      
            console.debug( 'somebody enter this room without stream' )
        }
    })


script>
body>
html>

总结

经测试,h5端IOS微信内置浏览器不支持调用,Android浏览器允许打开摄像头情况下调用正常。

你可能感兴趣的:(RTC,腾讯实时音视频,TRTC)