Google Cast(Chromecast)瀏覽器 SDK 學習筆記(一)

前幾天由於京東打折,買了個索尼的 SRS-X77 音箱,看說明書說支持 Google Cast,試了試感受還挺好用,因而研究了一下 Google Cast 的 SDK。javascript

Chromecast、Google Cast 傻傻分不清楚?

Google 在 2013 年推出了一個叫 Chromecast 的硬件,它運行一個精簡版的 Chrome OS,用戶可使用手機或者電腦(Chrome 瀏覽器)來控制它播放網絡或者本地的視頻、照片等。Google 隨之發佈了適用於 iOS、Android 和 Chrome 瀏覽器的 SDK。2015 年,Google 又發佈了 Chromecast Audio,它沒有 HDMI 接口,只能播放音頻。Google 給Chromecast 使用的這套技術命名爲 Google Cast。java

也就是說, Chromecast 是 Google 推出的硬件產品的名稱,Google Cast 指的是是這套經過網絡播放媒體技術,好比對應蘋果的 AirPlay。除了 Chromecast 系列硬件自己,Android TV 也支持做爲 Google Cast 的接收端,此外,索尼、LG 等廠商也製造了一些支持 Google Cast 的音響系統,固然也就包含了我買的索尼 SRS-X 系列。web

Google Cast 大體工做原理

發送端 app(sender app)使用 SDK,將須要播放的媒體的信息發送到 Google 的服務器,服務器再通知接收端播放(因此發送端和接收端必須均可以訪問 Google 的服務器才行)。接收端運行的是一個瀏覽器,它會根據發送端的app ID和媒體信息,去載入對應的一個網頁這個網頁(receiver app)也是由發送端 app 的開發者提供的,的將會負責播放相應的媒體內容。即便接收端時 Chromecast Audio 之類只能播放音頻的硬件,這個網頁也是會載入並渲染的。chrome

Google Cast 和 DLNA 或者蘋果的 AirPlay 不一樣之處,一是依賴 Google 的服務器,也就是說必須鏈接到 Internet 才能夠用,若是隻有一個局域網是不行的。二是前兩個的接收端播放器接收端自己提供的,開發者只須要提供要播放的內容就能夠,可是 Google Cast 則是須要提供本身的receiver app,這樣的好處是開發者能夠高度定製(好比能夠定製UI,或者加入彈幕、歌詞滾動、音樂可視化之類複雜功能),雖然接收端每每運行的並非Android這樣的開放操做系統,可是由於receiver app的本質是網頁,因此開發難度並不高。api

不過,若是你不須要定製化的receiver app,Google也提供了一套默認的receiver app,擁有最基本的音視頻播放的功能。瀏覽器

固然,以上只是根據我對 Google 的文檔的理解總結的,若是有什麼錯誤請指出。服務器

Google Cast 一些概念的介紹

  • 發送端(sender)
    能夠是Chrome 瀏覽器(電腦版或者 Android 版)、Android 設備、iOS 設備。網絡

  • 發送端 app(sender app)
    使用了 Google Cast SDK 的 app,能夠是 web app(網頁)也能夠是 Android 或 iOS app。session

  • 接收端(receiver)
    支持做爲接收端的硬件,如Chromecast、機頂盒、音箱、電視之類。app

  • 接收端 app(receiver app)
    接收端上運行的 app,由 sender 指定的 app ID 決定,其本質是網頁,接收端上的瀏覽器將其載入並執行。

  • session
    Sender 首先要跟特定的 receiver 創建 session 才能相互通訊。創建 session 對於用戶來講就是「設備配對」的過程。

  • media
    Session 創建後,Sender 可使用 session 的 loadMedia 方法來告訴 receiver 播放媒體。若是 loadMedia 成功,Sender 會得到一個 media 對象。該對象反映了receiver app正在播放的媒體,其中包含了播放狀態,播放隊列等信息。

使用 SDK 製做一個簡單的 sender app

下面咱們跟着官方教程,用 Chrome 瀏覽器的 SDK(Javascript)製做一個簡單的 sender app。由於註冊 app ID 要交五美圓因此我就直接使用默認的 receiver app 了。

引入 SDK

固然第一步就是在頁面中引入 SDK:

<script type="text/javascript" src="https://www.gstatic.com/cv/js/sender/v1/cast_sender.js"></script>

SDK使用了chrome.cast這個namespace。

初始化:

function onError(error) {
  console.log(error);
}

function onInitSuccess() {
  console.log('API successfully initialized');
}

function initializeCastApi() {
  const appID = chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID;
  const sessionRequest = new chrome.cast.SessionRequest(applicationID);
  const apiConfig = new chrome.cast.ApiConfig(sessionRequest,
    sessionListener,
    receiverListener);
  chrome.cast.initialize(apiConfig, onInitSuccess, onError);
};

window['__onGCastApiAvailable'] = function(loaded, errorInfo) {
  if (loaded) {
    console.log('API available');
    initializeCastApi();
  } else {
    console.log(errorInfo);
  }
}

咱們須要監聽__onGCastApiAvailable這個自定義事件,來執行 initializeCastApiinitializeCastApi 須要知道咱們的 app ID(若是使用默認的 receiver app 則使用 chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID 這個常量。sessionListenerreceiverListener 是什麼呢?下面說。

receiverListener 就是當receiver的狀態發生改變的時候觸發的回調函數。Google Cast 使用 mDNS 協議來實現設備發現,當有receiver被發現或者消失的時候,這個函數想會被觸發。好比咱們定義一個這樣的 receiverListener

let receiverIsAvailable = false;
function receiverListener(receiverAvailability) {
  console.log(`Receiver is ${receiverAvailability}`);
  receiverIsAvailable = (receiverAvailability === chrome.cast.ReceiverAvailability.AVAILABLE);
}

一開始個人音箱處於關機狀態,刷新頁面,控制檯顯示:

Receiver is unavailable

而後我把音箱打開,並鏈接到網絡,此時控制檯顯示:

Receiver is available

可見 receiverListener 的調用是實時的,可是這個函數並不知道有幾個 receivers,更不知道 receivers 的具體信息——其惟一參數是一個字符串 unavailable 或者 available,將其與 chrome.cast.ReceiverAvailability.AVAILABLE 常量比較來肯定是否available。

sessionListener 是當存在 session 的時候調用的函數。當咱們第一次初始化頁面的時候,尚未創建 session,因此這個函數並無被調用,可是若是咱們已經創建了 session,那麼再次刷新這個頁面時,SDK 便會發現已經存在的 session 並調用這個函數。在這個函數中咱們能夠把 session 存儲起來,供之後調用:

let currentSession = null;

function sessionListener(session) {
  currentSession = session;
  console.log('Current session updated');
}

創建 session(設備配對)

function onRequestSessionSuccess(session){
  console.log(session);
  currentSession = session;
  console.log('Current session updated');
}

function requestSession(){
  if(!currentSession){
    chrome.cast.requestSession(onRequestSessionSuccess, onError);
  }
}

設備配對須要客戶端主動執行,好比咱們能夠在頁面上放一個按鈕,用戶按下的時候就執行 requestSession。執行後咱們能夠看到 Chrome 彈出設備列表,這個列表是 Chrome 瀏覽器自己提供的:

設備選擇界面1

能夠看到個人音箱已經跟 Google Play Music 配對了,不過咱們須要它跟目前的頁面配對,點擊音箱名稱,而後點擊「投射」,音箱就會跟 Play Music 斷開而後跟咱們這個頁面創建 session。

設備選擇界面2

若是創建 session 成功就會調用 onRequestSessionSuccess,這個函數跟前面說的 sessionListener 是差很少的。

把 session 打印出來,是這樣的:

session

能夠看到 session 是由 sender app 和 receiver 決定的,只有咱們創建了 session 才能獲得具體的 receiver(以前咱們只知道 receiver 是否 avilable,不知道 receiver 有哪些),能夠知道 receiver 能支持音頻仍是視頻等。當咱們再次載入頁面的時候,由於 appId 相同,因此初始化階段就能夠觸發 sessionListener 咱們能夠這時就得到 session 而不須要再進行 requestSession 的操做了。注意個人音箱以前跟 Google Play Music 以前有一個 session 可是並無觸發個人頁面的 sessionListener,由於 appId 不一樣。

播放媒體

如今有了 session,咱們終於能夠命令 receiver 播放媒體了!

let currentMedia = null;

function onMediaDiscovered(how, media) {
  currentMedia = media;
}

function loadMedia(){
  const mediaInfo = new chrome.cast.media.MediaInfo('http://example.com/example.mp3');
  const request = new chrome.cast.media.LoadRequest(mediaInfo);
  session.loadMedia(request,
    onMediaDiscovered.bind(this, 'loadMedia'),
    onError);
}

執行完 loadMedia 不一會,應該就能夠聽到音箱發出聲音了✌️。

返回的 media 對象能夠用來控制播放:

currentMedia.pause();
currentMedia.play();
currentMedia.stop();
相關文章
相關標籤/搜索