小程序與WebRTC聯姻能擦出怎樣的火花?


歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐干貨哦~

本文由騰訊視頻雲終端團隊發表於雲+社區專欄

騰訊視頻雲終端技術總監,rexchang(常青), 2008 年畢業加入騰訊,一直從事客戶端研發相關工作,先后參與過 PC QQ、手機QQ、QQ物聯 等產品項目,目前在騰訊視頻雲團隊負責音視頻終端解決方案的優化和落地工作,幫助客戶在可控的研發成本投入之下,獲得業內一流的音視頻解決方案,目前我們的產品線包括:互動直播、點播、短視頻、實時視頻通話,圖像處理,AI 等等。

img本篇文章的思維導圖

分開做一下介紹

小程序音視頻是什么?

2017年騰訊視頻雲團隊跟微信團隊聯合,將視頻雲 SDK 跟微信小程序整合在一起,並通過 兩個標簽的形式開放內部的功能。通過這兩個標簽,開發者可以實現在線直播、低延時監控、雙人視頻通話以及多人視頻會議等功能。

那么WebRTC又是什么?

WebRTC(Web Real-Time Communication),是一個支持網頁瀏覽器進行實時語音對話或視頻對話的技術,是谷歌收購 GIPS 公司而獲得的一項技術,在 Chrome 瀏覽器上無需安裝插件,通過 javascript 就可以編寫實時音視頻通話程序。

兩者區別在哪里?

如果您跟我一樣是一個實用主義者,那我就簡單從實用主義角度說一下我的結論:小程序搞定了手機,WebRTC拿下了PC。

如果你對技術比較感興趣,那我們就可以從多個技術的角度去列舉兩者的區別,下面是一張詳細對比的表格:

img

  • 實現原理: 小程序音視頻是將騰訊視頻雲的 liteavsdk 嵌入到微信內部實現的,然后通過 兩個標簽將 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暴露十幾個接口類,而是繼續采用小程序音視頻的 標簽來解決問題。

其次,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)了。而房間的門板上始終寫着:“目前在房間里有哪幾個人”。

有了房間的概念,我們就可以將小程序的兩個簡單的 標簽,同 WebRTC 那一套復雜的 API 進行功能上的對齊,我們甚至不需要修改我們在第一版中定義的接口,就可以達成這個目標:

img

(1) 的 url 接口不再傳遞 rtmp:// 協議的推流地址,而是傳遞 room:// 協議的推流地址。room:// 協議的使用方式可以參考我們的原理版文檔 DOC

(2) 標簽在 start 成功之后,就相當於成功進入一個 room,之后,您可以通過 onPushEvent (PUSH_EVT_ROOM_USERLIST = 1020) 事件,收到房間里還有那些人的信息。在視頻通話期間,房間內各個成員的進進出出,也都會通過這個事件通知給您的小程序代碼。

(3)ROOM_USERLIST 里每一項都是一個二元組(如果是 1v1 的視頻通話,ROOM_USERLIST 里只會有一個人): userid 和 playurl。 userid 代表是哪個用戶, playurl 則是這個用戶遠程畫面的播放地址。您要做的只是使用 標簽播放這些遠程畫面的圖像和聲音而已。

(4)在 WebRTC 這一端,您可以參考我們的 webrtc API,這套 API 相對於 WebRTC 原生的 API,更適合初學者使用。

如何快速接入?

如果您希望一天內就打通 webrtc 和 小程序音視頻 的互通,那么我推薦您不要從零開始,因為那會耗費您太多時間去踩坑和 bugfix,推薦您直接使用我們封裝好的 ,這套方案既可以幫助您完成快速接入,又能滿足一定的定制需求。

另外,不要忘記在微信=>發現=>小程序=>騰訊雲視頻雲,體驗一下騰訊雲官方 Demo 中的 WebRTC 互通效果哦。

img

標簽說明

標簽是基於 實現的用於 WebRTC 互通的自定義組件。如果您希望直接使用 標簽完成對接,或者想要了解 的內部原理,可以參考 DOC

版本要求

  • 微信 6.6.6 版本開始支持。

效果演示

  • PC 端 用 Chrome 瀏覽器打開 體驗頁面 可以體驗桌面版 WebRTC 的效果。
  • 微信端 發現=>小程序=>搜索“騰訊視頻雲”,點擊 WebRTC 功能卡,就可以體驗跟桌面版 Chrome 互通的效果了。

img

對接資料

對接資料 說明 下載鏈接
小程序源碼 包含 的組件源碼以及demo源碼 DOWNLOAD
PC端源碼 基於WebrtcAPI實現的Chrome版WebRTC接入源碼(其中 component/WebRTCRoom.js 實現了一個簡單的房間管理功能,component/mainwindow.js包含了對 WebRTC API 的使用代碼) webrtc(Chrome).zip
后台源碼 實現了一個簡單的房間列表功能,同時包含 幾個所需參數的生成代碼 webrtc_server_list.zip

標簽詳解

屬性定義

屬性 類型 說明
template String '1v3' 必要,標識組件使用的界面模版(用戶如果需要自定義界面,請看 界面定制
sdkAppID String ‘’ 必要,開通 IM 服務所獲取到的 AppID
userID String '' 必要,用戶 ID
userSig String ‘’ 必要,身份簽名,相當於登錄密碼的作用
roomID Number ‘’ 必要,房間號
privateMapKey String ‘’ 必要,房間權限 key,相當於進入指定房間 roomID 的鑰匙
beauty Number 0~5 可選,默認 5, 美顏級別 0~5
muted Boolean true, false 可選,默認 false,是否靜音
debug Boolean true, false 可選,默認 false,是否打印推流 debug 信息
bindRoomEvent function 必要,監聽 組件返回的事件
enableIM Boolean true, false 可選,默認false
bindIMEvent function 當IM開啟時必要,監聽 IM 返回的事件

操作接口

組件包含如下操作接口,您需要先通過 selectComponent 獲取 標簽的引用,之后就可以進行相應的操作了。

函數名 說明
start() 啟動
pause() 暫停
resume() 恢復
stop() 停止
switchCamera() 切換攝像頭
var webrtcroom = this.selectComponent("#webrtcroomid")
webrtcroom.pause();

事件通知

標簽通過 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: 下載自定義組件源碼

並非微信小程序原生提供的標簽,而是一個自定義組件,所以您需要額外的代碼來支持這個標簽。點擊 小程序源碼 下載源碼包,您可以在 wxlite 文件夾下獲取到所需文件。

step2: 在工程中引入組件

  • 在 page 目錄下的 json 配置文件內引用組件,這一步是必須的,因為 並非原生標簽。 "usingComponents": { "webrtc-room": "/pages/webrtc-room/webrtc-room" }
    在 page 目錄下的 wxml 文件中使用標簽

step3: 獲取 key 信息

按照如下表格獲取關鍵的 key 信息,這是使用騰訊雲互通直播服務所必須的幾個信息:

KEY 示例 作用 獲取方案
sdkAppID 1400087915 用於計費和業務區分 step1 中獲取
userID xiaoming 用戶名 可以由您的服務器指定,或者使用小程序的openid
userSig 加密字符串 相當於 userid 對應的登錄密碼 由您的服務器簽發(PHP / JAVA
roomID 12345 房間號 可以由您的服務器指定
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();
	}
})

界面定制

  • 創建界面模版
//第一步:新建 /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 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社區


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM