歡迎你們前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~javascript
本篇文章的思惟導圖騰訊視頻雲終端技術總監,rexchang(常青), 2008 年畢業加入騰訊,一直從事客戶端研發相關工做,前後參與過 PC QQ、手機QQ、QQ物聯 等產品項目,目前在騰訊視頻雲團隊負責音視頻終端解決方案的優化和落地工做,幫助客戶在可控的研發成本投入之下,得到業內一流的音視頻解決方案,目前咱們的產品線包括:互動直播、點播、短視頻、實時視頻通話,圖像處理,AI 等等。git
小程序音視頻是什麼?github
2017年騰訊視頻雲團隊跟微信團隊聯合,將視頻雲 SDK 跟微信小程序整合在一塊兒,並經過 和 兩個標籤的形式開放內部的功能。經過這兩個標籤,開發者能夠實如今線直播、低延時監控、雙人視頻通話以及多人視頻會議等功能。web
那麼WebRTC又是什麼?算法
WebRTC(Web Real-Time Communication),是一個支持網頁瀏覽器進行實時語音對話或視頻對話的技術,是谷歌收購 GIPS 公司而得到的一項技術,在 Chrome 瀏覽器上無需安裝插件,經過 javascript 就能夠編寫實時音視頻通話程序。json
若是您跟我同樣是一個實用主義者,那我就簡單從實用主義角度說一下個人結論:小程序搞定了手機,WebRTC拿下了PC。小程序
若是你對技術比較感興趣,那咱們就能夠從多個技術的角度去列舉二者的區別,下面是一張詳細對比的表格:微信小程序
WebRTC 由谷歌收購 GIPS 得來(這裏不得不提一下,我加入騰訊時所在的第一個團隊就是 QQ 團隊,當時 QQ 的音視頻仍是購買的 GIPS 公司的產品,不過因爲各類不靠譜,後來就轉爲自研路線了)。因此其技術被完整的保留而且加入到了 Google 的 Chrome 瀏覽器內核當中。並且最近蘋果也已經開始在 Safari 瀏覽器中支持 WebRTC 的相關能力。api
WebRTC的底層則是使用RTP和RTCP兩種數據協議,其中RTP主要用於音視頻數據傳輸,而RTCP則通常用於控制。
WebRTC在這裏則要尷尬的多,一方面Android系統的碎片化自己讓WebRTC的具體表現呈現「百花齊放」的景象,同時,iOS 目前的內嵌WebView(也就是在微信等APP裏打開的各類內嵌網頁)不支持WebRTC也仍是個很麻煩的問題。
相比之下,WebRTC則不是一個團隊或者一家公司的問題了,由於它如今已經走標準路線,因此每個新特性都是先肯定標準,而後再推進瀏覽器廠商(包括蘋果)進行跟隨。這裏面的故事就多了,時間也就更久了。
可是在桌面瀏覽器這個部分,Chrome目前在PC瀏覽器市場上留到地位的存在決定了 WebRTC 的優點就很大了,開發者能夠在不安裝插件的狀況下就能夠實現本身想要的功能。
相比之下,因爲沒有 Chrome 的原生支持,因此若是咱們要在 PC 上對接小程序音視頻,就須要安裝瀏覽器插件或者經過 wxlite://start 這樣的僞協議喚起本地 exe 應用程序(相似在網頁上打開 QQ 聊天窗口)。
小程序音視頻和WebRTC支架並不是零和博藝,雙方都有本身的優點和不足,因此本着「打不過他們,就加入他們」的思路,騰訊視頻雲團隊在2018年春節回來後,就快馬加鞭地開始了小程序音視頻和WebRTC互通的相關工做。
目前,須要向各位開發者彙報的是,在最新版本的微信中,小程序音視頻已經能夠跟WebRTC打通,目前在PC 的Chrome瀏覽器上就能夠跟小程序進行實時音視頻互通。
// to-do
固然,若是您想知道這個功能是怎麼實現的,能夠繼續看下去:
就像結婚同樣,既然你決定要選擇另外一我的做爲人生下半輩子的伴侶,那你確定會先深刻地瞭解一下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互通問題上所採起的方案:
(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 進行功能上的對齊,咱們甚至不須要修改咱們在初版中定義的接口,就能夠達成這個目標:
(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 互通效果哦。
標籤是基於 和 實現的用於 WebRTC 互通的自定義組件。若是您但願直接使用 和 標籤完成對接,或者想要了解 的內部原理,能夠參考 DOC。
對接資料 | 說明 | 下載連接 |
---|---|---|
小程序源碼 | 包含的組件源碼以及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部署 開通了相關服務和並正確的完成了配置。
並不是微信小程序原生提供的標籤,而是一個自定義組件,因此您須要額外的代碼來支持這個標籤。點擊 小程序源碼 下載源碼包,您能夠在 wxlite
文件夾下獲取到所需文件。
按照以下表格獲取關鍵的 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)。
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> 組件中的 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";
複製代碼
瞭解騰訊雲官網的 WebrtcAPI ,能夠對接 Chrome 端的 H5 視頻通話,由於不是本文檔的重點,此處不作贅述。
實時音視頻產品開通
想要嘗試這些接入,首先要開通騰訊雲實時音視頻,快來接入吧~
問答
相關閱讀
此文已由做者受權騰訊雲+社區發佈,更多原文請點擊
搜索關注公衆號「雲加社區」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!