小程序与WebRTC联姻能擦出怎么的火花?

作者 : 开心源码 本文共10754个字,预计阅读时间需要27分钟 发布时间: 2022-05-12 共226人阅读

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~

本文由腾讯视频云终端团队发表于云+社区专栏

腾讯视频云终端技术总监,rexchang(常青), 2008 年毕业加入腾讯,一直从事用户端研发相关工作,先后参加过 PC QQ、手机QQ、QQ物联 等产品项目,目前在腾讯视频云团队负责音视频终端处理方案的优化和落地工作,帮助用户在可控的研发成本投入之下,取得业内一流的音视频处理方案,目前我们的产品线包括:互动直播、点播、短视频、实时视频通话,图像解决,AI 等等。

img

本篇文章的思维导图

分开做一下详情

小程序音视频是什么?

2017年腾讯视频云团队跟微信团队联合,将视频云 SDK 跟微信小程序整合在一起,并通过 <live-pusher> 和 <live-player> 两个标签的形式开放内部的功能。通过这两个标签,开发者可以实现在线直播、低延时监控、双人视频通话以及多人视频会议等功能。

那么WebRTC又是什么?

WebRTC(Web Real-Time Communication),是一个支持网页浏览器进行实时语音对话或者视频对话的技术,是谷歌收购 GIPS 公司而取得的一项技术,在 Chrome 浏览器上无需安装插件,通过 javascript 即可以编写实时音视频通话程序。

两者区别在哪里?

假如您跟我一样是一个实使用主义者,那我就简单从实使用主义角度说一下我的结论:小程序搞定了手机,WebRTC拿下了PC。

假如你对技术比较感兴趣,那我们即可以从多个技术的角度去列举两者的区别,下面是一张详细比照的表格:

img

  • 实现原理: 小程序音视频是将腾讯视频云的 liteavsdk 嵌入到微信内部实现的,而后通过 <live-pusher> 和 <live-player> 两个标签将 SDK 内部的音视频能力开放出来。所以小程序的标签起到了开发者 API 的作使用,而内部的 SDK 则是真正使用来实现音视频功能。

WebRTC 由谷歌收购 GIPS 得来(这里不得不提一下,我加入腾讯时所在的第一个团队就是 QQ 团队,当时 QQ 的音视频还是购买的 GIPS 公司的产品,不过因为各种不靠谱,后来就转为自研路线了)。所以其技术被完整的保留并且加入到了 Google 的 Chrome 浏览器内核当中。而且最近苹果也已经开始在 Safari 浏览器中支持 WebRTC 的相关能力。

  • 底层协议 小程序音视频的主要协议是目前在直播领域最为常使用的 RTMP 推流协议,以及 HTTP-FLV 播放协议,这两种协议都已经有多年的沉淀而且在互联网上的资料也是汗牛充栋。

WebRTC的底层则是用RTP和RTCP两种数据协议,其中RTP主要使用于音视频数据传输,而RTCP则一般使用于控制。

  • 手机端碎片化问题 小程序音视频因为是微信统一实现的,而且微信团队每个版本都尽量要求功能对齐,否则宁可不上,所以在碎片化问题上基本不存在。

WebRTC在这里则要尴尬的多,一方面Android系统的碎片化本身让WebRTC的具体体现呈现“百花齐放”的景象,同时,iOS 目前的内嵌WebView(也就是在微信等APP里打开的各种内嵌网页)不支持WebRTC也还是个很麻烦的问题。

  • 扩展性 小程序音视频跟随微信的版本发布,有什么问题一般是当前代码流修正,而后跟随下一个版本发布,所以一般一个功能点(比方给 pusher 加一个美颜的功能)或者者一个问题点(比方不支持手势放大)从确立到最终实现(或者处理)仅需要一个月的时间,而且微信APP新版本的覆盖速度也的确挺快。

相比之下,WebRTC则不是一个团队或者者一家公司的问题了,由于它现在已经走标准路线,所以每一个新特性都是先确定标准,而后再推动浏览器厂商(包括苹果)进行跟随。这里面的故事就多了,时间也就更久了。

  • 桌面浏览器 相信您已经发现,在前面几个问题的分析上,我的观点都倾向小程序音视频。的确,在目前国内的移动领域里,谷歌和苹果都不能一家说了算,真正说了算的还是微信

但是在桌面浏览器这个部分,Chrome目前在PC浏览器市场上留到地位的存在决定了 WebRTC 的优势就很大了,开发者可以在不安装插件的情况下即可以实现自己想要的功能。

相比之下,因为没有 Chrome 的原生支持,所以假如我们要在 PC 上对接小程序音视频,就需要安装浏览器插件或者者通过 wxlite://start 这样的伪协议唤起本地 exe 应使用程序(相似在网页上打开 QQ 聊天窗口)。

并非零和博弈

小程序音视频和WebRTC支架并非零和博艺,双方都有自己的优势和不足,所以本着“打不过他们,就加入他们”的思路,腾讯视频云团队在2018年春节回来后,就马不停蹄地开始了小程序音视频和WebRTC互通的相关工作。

目前,需要向各位开发者汇报的是,在最新版本的微信中,小程序音视频已经可以跟WebRTC打通,目前在PC 的Chrome浏览器上即可以跟小程序进行实时音视频互通。

// to-do

当然,假如您想知道这个功能是怎样实现的,可以继续看下去:

充分理解WebRTC

就像结婚一样,既然你决定要选择另一个人作为人生下半辈子的伴侣,那你一定会先深入地理解一下TA这个人,比方性格,脾气,爱好等各个方面。

同样,我们要想很好的将小程序音视频和WebRTC打通,那也必需要多理解一下WebRTC,这里我就说一下我对 WebRTC 这个“人” 在性格上的少量了解。

首先,她尽管长得不太好看,但很有内涵。

说WebRTC长得不好看,只是我的一种比喻,我的意思是想说WebRTC的学习成本不低,尽管Google做了很多通俗易懂的PPT来教你怎样 Getting Start,但真要完整的学进去,还是需要静下心来,慢慢地把她当成自己认可的目标去学下去。但是假如你是第一次恋爱(也就是第一次接触实时音视频),你会发现学习WebRTC的过程,本身就是理解一个实时音视频技术细节的过程。

其次,她非常喜欢迁就别人,各种架构方案她都能支持到。

说WebRTC喜欢迁就比人,也是一种比喻,WebRTC所支持的后端架构非常多(比方 Mixer, Mesh,Router),而且谷歌认为这些后端实现都比较简单,所以既没有开放后端相关的源码,也没有提供统一的后端处理方案。这种开放式的设计思路非常好,但反作用就是实现成本高。在真刀真枪的项目落地时,小规模的公司或者者开发者就很容易被这种技术门槛挡在门外。尤其是想要将 WebRTC 真正应使用到企业级处理方案中,面对录制和存档的刚性需求,就需要花费大量时间进行定制开发。

方案确实立

理解到 WebRTC 的这些特点后,我们的互通方案也就比较清晰了:

首先,小程序音视频的特点是接口简单,快速上手,这是小程序的优势;而这一点恰恰是WebRTC的劣势,所以我们没有必要在小程序端为WebRTC暴露十几个接口类,而是继续采使用小程序音视频的 <live-pusher> 和 <live-player> 标签来处理问题。

其次,WebRTC 的后端没有官方实现,那就意味着这里有很大的发挥空间,腾讯视频云即可以实现一套WebRTC后端并将其同小程序音视频所用RTMP后端进行打通。简单来说,腾讯视频云要在小程序音视频和WebRTC之间充任红娘(更确切的说,应该是翻译员)的角色。

但是看过《新闻联播》里国家领导人之间谈话镜头的人都知道,这种翻译是会影响交流速度的。小程序音视频和WebRTC之间互通,中间引入一个翻译员,是不是通讯延时也就添加了?

其实不会,由于小程序音视频和WebRTC的视频编码标准在常规应使用场景中是一致的,都是H.264标准,这是音频格式不同而已。这就意味着,翻译员要做的事情很少,两边基本都能挺对对方在说什么,所以延时不会添加太多。

成功的握手

下图所展现的就是腾讯视频云在小程序音视频和WebRTC互通问题上所采取的方案:

img

(1)首先,微信端的小程序通过腾讯视频云SDK将音视频流推送到腾讯云 RTMP 服务器。

(2)其次,腾讯云 RTMP 服务器的会对音视频数据进行初步的转化解决,而后透传给腾讯视频云的实时音视频后端集群。

(3)再次,实时音视频后端会再次将数据交给一个叫做 WebRTC-Proxy 的板块,就在这里, WebRTC-Proxy 要将来自小程序音视频的音视频数据翻译成 WebRTC 了解的“语言”。

(4)最后,在PC上的Chrome浏览器,即可以通过浏览器内置的WebRTC板块跟 WebRTC-Proxy 通讯,进而看到小程序端的视频影像。

(5)上面的四个过程倒过来,即可以实现双向视频通话;而将腾讯视频云作为星型结构的中心节点,多个端(不论是小程序还是Chrome浏览器)都接入进来,那即可以形成多人音视频处理方案。

打通房间逻辑

仅仅完成了音视频数据在小程序和WebRTC之间的握手还远远不够,由于在一次成功的音视频通话背后,不仅仅是把一端的音视频数据传递到另一端这么简单,还有状态的同步和成员间的状态协同。

比方多人视频通话中,涉及到呼叫和接通的流程,其中一方假如挂断了,其余人要收到挂断的通知。同时,假如有新的参加者加入,那么其余人也要收到相应的通知。WebRTC 中有很多组件,比方 RTCPeerConnection 就在解决上诉林林种种的逻辑。但是 WebRTC 的接口中引入的新名词非常多,对于初学者来说还是有肯定的入门门槛,为了简化这里的逻辑,我们引入一个叫做“房间”的概念。

所谓房间(Room),就是把同时参加视频通话的各方圈在一起的一个东西。比方双人通话中,通话中的两个人 A 和 B 即可以认为在一个房间中。再比方在多人通话中,通话中的五个人(A B C D E)也可以认为是在一个房间里。

有了房间的概念,那我们即可以对刚才说的状态协同使用两个简单的动作形容一下:假如有一个人加入了视频通话,那么即可以了解为他/她已经进房(EnterRoom)了;假如有一个退出了视频通话,那么即可以了解为他/她已经离开房间(LeaveRoom)了。而房间的门板上始终写着:“目前在房间里有哪几个人”。

有了房间的概念,我们即可以将小程序的两个简单的 <live-pusher> 和 <live-player> 标签,同 WebRTC 那一套复杂的 API 进行功能上的对齐,我们甚至不需要修改我们在第一版中定义的接口,即可以达成这个目标:

img

(1)<live-pusher> 的 url 接口不再传递 rtmp:// 协议的推流地址,而是传递 room:// 协议的推流地址。room:// 协议的用方式可以参考我们的原理版文档 DOC。

(2)<live-pusher> 标签在 start 成功之后,就相当于成功进入一个 room,之后,您可以通过 onPushEvent (PUSH_EVT_ROOM_USERLIST = 1020) 事件,收到房间里还有那些人的信息。在视频通话期间,房间内各个成员的进进出出,也都会通过这个事件通知给您的小程序代码。

(3)ROOM_USERLIST 里每一项都是一个二元组(假如是 1v1 的视频通话,ROOM_USERLIST 里只会有一个人): userid 和 playurl。 userid 代表是哪个使用户, playurl 则是这个使用户远程画面的播放地址。您要做的只是用 <live-player> 标签播放这些远程画面的图像和声音而已。

(4)在 WebRTC 这一端,您可以参考我们的 webrtc API,这套 API 相对于 WebRTC 原生的 API,更适合初学者用。

如何快速接入?

假如您希望一天内就打通 webrtc 和 小程序音视频 的互通,那么我推荐您不要从零开始,由于那会耗费您太多时间去踩坑和 bugfix,推荐您直接用我们封装好的 ,这套方案既可以帮助您完成快速接入,又能满足肯定的定制需求。

另外,不要不记得在微信=>发现=>小程序=>腾讯云视频云,体验一下腾讯云官方 Demo 中的 WebRTC 互通效果哦。

img

标签说明

<webrtc-room> 标签是基于 <live-pusher> 和 <live-player> 实现的使用于 WebRTC 互通的自己设置组件。假如您希望直接用 <live-pusher> 和 <live-player> 标签完成对接,或者者想要理解 <webrtc-room> 的内部原理,可以参考 DOC。

版本要求

  • 微信 6.6.6 版本开始支持。

效果演示

  • PC 端 使用 Chrome 浏览器打开 体验页面 可以体验桌面版 WebRTC 的效果。
  • 微信端 发现=>小程序=>搜索“腾讯视频云”,点击 WebRTC 功能卡,即可以体验跟桌面版 Chrome 互通的效果了。

img

对接资料

对接资料说明下载链接
小程序源码包含<webrtc-room>的组件源码以及demo源码DOWNLOAD
PC端源码基于WebrtcAPI实现的Chrome版WebRTC接入源码(其中 component/WebRTCRoom.js 实现了一个简单的房间管理功能,component/mainwindow.js包含了对 WebRTC API 的用代码)webrtc(Chrome).zip
后端源码实现了一个简单的房间列表功能,同时包含<webrtc-room>几个所需参数的生成代码webrtc_server_list.zip

标签详解

属性定义

属性类型说明
templateString‘1v3’必要,标识组件用的界面模版(使用户假如需要自己设置界面,请看 界面定制)
sdkAppIDString‘’必要,开通 IM 服务所获取到的 AppID
userIDString必要,使用户 ID
userSigString‘’必要,身份签名,相当于登录密码的作使用
roomIDNumber‘’必要,房间号
privateMapKeyString‘’必要,房间权限 key,相当于进入指定房间 roomID 的钥匙
beautyNumber0~5可选,默认 5, 美颜级别 0~5
mutedBooleantrue, false可选,默认 false,能否静音
debugBooleantrue, false可选,默认 false,能否打印推流 debug 信息
bindRoomEventfunction必要,监听 <webrtc-room> 组件返回的事件
enableIMBooleantrue, false可选,默认false
bindIMEventfunction当IM开启时必要,监听 IM 返回的事件

操作接口

<webrtc-room> 组件包含如下操作接口,您需要先通过 selectComponent 获取 <webrtc-room> 标签的引使用,之后即可以进行相应的操作了。

函数名说明
start()启动
pause()暂停
resume()恢复
stop()中止
switchCamera()切换摄像头
var webrtcroom = this.selectComponent("#webrtcroomid")webrtcroom.pause();

事件通知

<webrtc-room> 标签通过 onRoomEvent 返回内部事件,通过 onIMEvent 返回 IM 消息事件,事件参数格式如下

"detail": {  "tag": "事件tag标识,具备唯一性",  "code": "事件代码",  "detail": "对应事件的详细参数"}

示例代码

// Page.wxml 文件<webrtc-room id="webrtcroom"    roomID="{{roomID}}"    userID="{{userID}}"    userSig="{{userSig}}"    sdkAppID="{{sdkAppID}}"    privateMapKey="{{privateMapKey}}"    template="1v3"    beauty="{{beauty}}"    muted="{{muted}}"    debug="{{debug}}"    bindRoomEvent="onRoomEvent"    enableIM="{{enableIM}}"    bindIMEvent="onIMEvent"></webrtc-room>// Page.js 文件Page({    data: {        //...        roomID: '',        userID: '',        userSig: '',        sdkAppID: '',        beauty: 3,        muted: false,        debug: false,        enableIM: false    },    onRoomEvent: function(e){        switch(e.detail.tag){            case 'error': {                //发生错误                var code = e.detail.code;                var detail = e.detail.detail;                break;            }        }    },    onIMEvent: function(e){        switch(e.detail.tag){            case 'big_group_msg_notify':                 //收到群组消息                console.debug( e.detail.detail )                break;            case 'login_event':                 //登录事件通知                console.debug( e.detail.detail )                break;            case 'connection_event':                 //连接状态事件                console.debug( e.detail.detail )                break;            case 'join_group_event':                 //进群事件通知                console.debug( e.detail.detail )                break;        }    },  onLoad: function (options) {        self.setData({            userID: self.data.userID,            userSig: self.data.userSig,            sdkAppID: self.data.sdkAppID,            roomID: self.data.roomID,            privateMapKey: res.data.privateMapKey        }, function() {            var webrtcroomCom = this.selectComponent('#webrtcroom');            if (webrtcroomCom) {                webrtcroomCom.start();            }        })    },    })

用指引

请确认已经参照 Demo部署 开通了相关服务和并正确的完成了配置。

step1: 下载自己设置组件源码

<webrtc-room> 并非微信小程序原生提供的标签,而是一个自己设置组件,所以您需要额外的代码来支持这个标签。点击 小程序源码 下载源码包,您可以在 wxlite 文件夹下获取到所需文件。

step2: 在工程中引入组件

  • 在 page 目录下的 json 配置文件内引使用组件,这一步是必需的,由于 <webrtc-room> 并非原生标签。 “usingComponents”: { “webrtc-room”: “/pages/webrtc-room/webrtc-room” }
    在 page 目录下的 wxml 文件中用标签<webrtc-room id=”webrtcroomid” roomID=”{{roomID}}” userID=”{{userID}}” userSig=”{{userSig}}” sdkAppID=”{{sdkAppID}}” privateMapKey=”{{privateMapKey}}” template=”1v3″ beauty=”{{beauty}}” muted=”{{muted}}” debug=”{{debug}}” bindRoomEvent=”onRoomEvent” enableIM=”{{enableIM}}” bindIMEvent=”onIMEvent”> </webrtc-room>

step3: 获取 key 信息

按照如下表格获取关键的 key 信息,这是用腾讯云互通直播服务所必需的几个信息:

KEY示例作使用获取方案
sdkAppID1400087915使用于计费和业务区分step1 中获取
userIDxiaoming使用户名可以由您的服务器指定,或者者用小程序的openid
userSig加密字符串相当于 userid 对应的登录密码由您的服务器签发(PHP / JAVA)
roomID12345房间号可以由您的服务器指定
privateMapKey加密字符串进房票据:相当于是进入 roomid 的钥匙由您的服务器签发(PHP / JAVA)

下载 sign_src.zip 可以取得服务端签发 userSig 和 privateMapKey 的计算代码(生成 userSig 和 privateMapKey 的签名算法是 ECDSA-SHA256)。

step4: 进入房间

self.setData({    userID: userID,    userSig: userSig,    sdkAppID: sdkAppID,    roomID: roomID,    privateMapKey: privateMapKey}, function() {    var webrtcroomCom = this.selectComponent('#webrtcroomid');    if (webrtcroomCom) {        webrtcroomCom.start();    }})

<h2 id=”CustomUI”> 界面定制 </h2>

  • 创立界面模版
//第一步:新建 /pages/templates/mytemplate 文件夹,并创立 mytemplate.wxml 和 mytemplate.wxss 文件//第二步:编写 mytemplate.wxml 和 mytemplate.wxss 文件//mytemplate.wxml<template name='mytemplate'>    <view class='videoview'>        <view class="pusher-box">            <live-pusher                id="rtcpusher"                autopush                mode="RTC"                url="{{pushURL}}"                aspect="{{aspect}}"                min-bitrate="{{minBitrate}}"                max-bitrate="{{maxBitrate}}"                audio-quality="high"                beauty="{{beauty}}"                muted="{{muted}}"                waiting-image="https://mc.qcloudimg.com/static/img/                                     daeed8616ac5df256c0591c22a65c4d3/pause_publish.jpg"                background-mute="{{true}}"                debug="{{debug}}"                bindstatechange="onPush"                binderror="onError">                <cover-image  class='character' src="/pages/Resources/mask.png"></cover-image>                <cover-view class='character' style='padding: 0 5px;'>我</cover-view>            </live-pusher>        </view>        <view class="player-box" wx:for="{{members}}" wx:key="userID">             <view class='poster'>                <cover-image class='set'                   src="https://miniprogram-1252463788.file.myqcloud.com/roomset_{{index + 2}}.png">                </cover-image>            </view>            <live-player                id="{{item.userID}}"                autoplay                mode="RTC"                wx:if="{{item.accelerateURL}}"                object-fit="fillCrop"                min-cache="0.1"                max-cache="0.3"                src="{{item.accelerateURL}}"                debug="{{debug}}"                background-mute="{{true}}"                bindstatechange="onPlay">                <cover-view class='loading' wx:if="{{item.loading}}">                    <cover-image src="/pages/Resources/loading_image0.png"></cover-image>                </cover-view>                <cover-image  class='character' src="/pages/Resources/mask.png"></cover-image>                <cover-view class='character' style='padding: 0 5px;'>{{item.userName}}</cover-view>            </live-player>          </view>     </view></template>//mytemplate.wxss.videoview {  background-repeat:no-repeat;  background-size: cover;  width: 100%;  height: 100%;}
  • webrtc-room 组件引入模版
//为 <webrtc-room> 组件中的 webrtcroom.wxml 文件增加自己设置模版<import src='/pages/templates/mytemplate/mytemplate.wxml'/><view class='conponent-box'>    <view styles="width:100%;height=100%;" wx:if="{{template=='1v3'}}">        <template is='mytemplate' data="{{pushURL, aspect,                       minBitrate, maxBitrate, beauty, muted, debug, members}}"/>    </view></view>//为 <webrtc-room> 组件中的 webrtcroom.wxss 文件增加自己设置样式@import "../templates/mytemplate/mytemplate.wxss";

Chrome端对接

理解腾讯云官网的 WebrtcAPI ,可以对接 Chrome 端的 H5 视频通话,由于不是本文档的重点,此处不做赘述。

实时音视频产品开通

想要尝试这些接入,首先要开通腾讯云实时音视频,快来接入吧~

问答
怎么部署小程序?
相关阅读
教你1天搭建自己的“微视”
教你从0到1搭建小程序音视频
教你快速搭建一场发布会直播方案
【每日课程推荐】新加坡南洋理工大学博士,带你深度学习NLP技术

此文已由作者受权腾讯云+社区发布,更多原文请点击

搜索关注公众号「云加社区」,第一时间获取技术干货,关注后回复1024 送你一份技术课程大礼包!

海量技术实践经验,尽在云加社区!

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 小程序与WebRTC联姻能擦出怎么的火花?

发表回复