iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 23
0
Modern Web

Webduino 不只是物聯網,智慧插座也可以很 Modern~系列 第 23

實戰智慧插座 23 - 用 Youtube 的魔術開關燈 ( 影片互動篇 )

前面我們使用了 Google 試算表還有 Google 地圖,接著來看 Google 的 Youtube ( 反正都滿好串接的,就直接使用看看 ),不過我們一般對 Youtube 的認知不就是播影片,能夠拿來玩智慧插座嗎?我想這就需要靠一些創意和想像了,這也是為什麼我要把這篇的名稱定為「 用 Youtube 的魔術開關燈」。



Youtube 起手式

要使用 Youtube 玩開關燈魔術的話,首先要了解相關的控制方式,這時候一定要來官方網站 Youtube 開發人員專區 看看,因為我們要在網頁裡面使用,就點選 IFrame Player API 閱讀。

Webduino Youtube

按照官方的教學,首先你的 HTML 需要有一個 div 來放影片。

<div id="player"></div>

再來 JavaScript 的起手式,要先載入用 Youtube 的 igrame API,

var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

或者你其實也可以直接在 HTML 引入對應的 JavaScript。

<script src="https://www.youtube.com/iframe_api"></script>

再來看到第一段,這邊指定了我們剛剛放在 HTML 的 div ( id 是 player ),以及開始播放時候的影片長寬尺寸,最重要的是 videoId 這段,這是我們要播放影片的 ID。

var player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
    events: {
      'onReady': onPlayerReady
    }
  });
}

影片的 ID 在哪裡呢?影片 ID 就是網址列 v= 後面的這一串代碼

Webduino Youtube

在上面那段程式碼裡,events 有個屬性叫做 onReady,這表示在 Youtube 播放區域準備好之後要做的流程是 onPlayerReady,所以我們要撰寫一段對應的流程,這個流程表示影片播放區域準備好之後,就開始播放影片。

function onPlayerReady(event) {
  event.target.playVideo();
}

或這樣寫也可以。

function onPlayerReady() {
   player.playVideo();
}

然後只要我們執行網頁,就可以看到 Youtube 影片開始播放了。

Webduino Youtube
( 程式:http://bin.webduino.io/hudaz/1/edit?html,js,output )

這邊要再說明一下,回到 onYouTubeIframeAPIReady() 這個流程,其實裡面的 player 還有另外一個重要的屬性叫做 playerVars,這邊包含了影片一開始的許多屬性設定,完整設定可以參考 Player parameters,比較常用的大概就是autoPlay 自動播放、controls 下方控制選單,以下面的例子來說,預設會自動播放,然後關閉下方控制選單。

function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
    playerVars:{
      autoplay:1,
      controls:0
    },
    events: {
      'onReady': onPlayerReady
    }
  });
}

如果你有仔細看 API 文件的話,一定會發現有一個方法叫做 loadVideoByUrl,顧名思義就是直接用網址就可以載入影片,總是比直接貼 ID 方便得多,但很可惜網址必須要遵照規範,也就是要長 http://www.youtube.com/v/VIDEO_ID?version=3 這個樣子的網址才可以,所以這個方法基本上也不是那麼的好用。

如果真的想要用網址,不如自己寫一段程式去篩選,下面這段是我寫出來篩選 Youtube 網址的程式,只要把網址貼在 u 的地方,就會回傳 ID 囉!
( 程式:http://bin.webduino.io/jexu/1/edit?html,js,output )

function getVideoId(u){
  var v, vid;
  if(u.indexOf('?v=')!=-1){
    v = u.split('?v=');
    if(v[1].indexOf('&')!=-1){
      vid = v[1].split('&')[0];
    }else{
      vid = v[1];
    }
    return vid;
  }else{
    return u;
  }
}


Youtube 操控方法

Youtube 載入之後有些預設的行為 ( events ),透過這些行為,我們可以決定何時要做什麼事情。

  • onReady:當 Youtube 準備好的時候
  • onStateChange:當 Youtube 狀態改變時 ( -1 尚未開始、0 結束、1 正在播放、2 暫停、3 buffering、5 video cue )
  • onPlaybackQualityChange:當 Youtube 品質設定改變時
  • onPlaybackRateChange:當Youtube 播放速度改變時
  • onError:當 Youtube 發生錯誤時
  • onApiChange:當 Youtube API 改變時

除了上面常見的行為,也有下面滿常用的一些 Youtube 的操控方法,其實另外還有「影片清單」操作方法,不過因為這篇沒有介紹到清單,加上官網內容也頗完整,如果對影片清單有興趣的就請移駕到 Youtube 開發人員專區 去看看了。

  • player.playVideo() :播放影片
  • player.pauseVideo() :暫停
  • player.stopVideo():停止
  • player.seekTo(sec):前往第幾秒 ( 1 分鐘 30 秒 = 90 秒 )
  • player.mute():靜音
  • player.unMute():取消靜音
  • player.isMuted():判斷是不是靜音 ( true / flase )
  • player.setVolume(Volumn):設定音量大小 ( 0~100 )
  • player.getVolume():取得當前音量大小 ( 0~100 )
  • player.setSize(width, height):設定影片尺寸
  • player.getPlaybackRate():取得播放速度 ( 0.25、0.5、1、1.5、2)
  • player.setPlaybackRate(suggestedRate):設定播放速度 ( 0.25、0.5、1、1.5、2)
  • player.getPlayerState():取得目前影片狀態 ( -1 尚未開始、0 結束、1 正在播放、2 暫停 )
  • player.getCurrentTime():取得目前影片播放時間 ( 需四捨五入轉換 )
  • player.getPlaybackQuality():取得目前影片品質 ( highres、hd1080、hd720、large、medium、small )
  • player.setPlaybackQuality(suggestedQuality):設定影片品質 ( highres、hd1080、hd720、large、medium、small )

透過上述的行為與方法,我們就可以自己安排一些簡單的行為去控制影片,例如我自己最喜歡的「影片結束後自動播放」、「歌唱比賽只重複播歌唱的部分,略過評審評語」的功能,這樣就可以一首歌用 Youtube 不斷重播了。
( 程式:http://bin.webduino.io/zobaw/1/edit?html,js,output )

var player;
function onYouTubeIframeAPIReady() {
  player = new YT.Player('player', {
    height: '390',
    width: '640',
    videoId: 'M7lc1UVf-VE',
    playerVars:{
      autoplay:1,
      controls:1,
      start:30
    },
    events: {
      'onReady': onPlayerReady,
      'onStateChange':onStateChange
    }
  });
}

function onPlayerReady() {
   player.playVideo();
}

function onStateChange(event){
  //event.data 返回現在影片的狀態 ( -1 尚未開始、0 結束、1 正在播放、2 暫停 )
  if(event.data===0){
    player.playVideo();
  }
}

甚至你不想聽到歌唱比賽評審的評語,你也可以輕鬆辦到「歌唱比賽只重複播歌唱的部分」,例如下面這首「宋楚琳 魔鬼中的天使」,前面也有介紹,後面又有評語,透過這些 Youtube 方法的操控,就可以只聽中間演唱的部分。( 唱得真的很有味道 XD,影片 ID:d5Xx_C0bK0Q )

function onPlayerReady() {
   player.playVideo();
   player.seekTo(92); //影片播放後前往 92 秒的位置
   //每一秒抓取一次現在影片的秒數
   setInterval(function(){
     var sec = Math.round(player.getCurrentTime()*10)/10; //四捨五入現階段秒數
     //如果秒數大於 240 秒就前往 92 秒
     if(sec>240){
       player.seekTo(92);
     }
   },1000);
}

Webduino Youtube
( 程式:http://bin.webduino.io/selet/1/edit?html,js,output )



讓 YouTube 和燈泡互動

既然我們已經可以透過網頁操控 Youtube 或是獲得 Youtube 的一些數值,接著就是要透過 Webduino 來把燈泡與影片做些互動,首先我們打開這支影片 ( https://www.youtube.com/watch?v=-6ZFeFuvan8 ),這是我用手往左揮和往右揮的影片 ( 雙下巴收不住... ),當影片的手揮到右邊,右邊的燈就會亮,揮到左邊,左邊的燈就會亮。( 把 Youtube 長寬設成 100% 就可以變成全螢幕囉 )

一開始一樣設定 onPlayerReady() 的事件,然後裡面就是在開發版都上線之後,執行 ready 的流程。

function onPlayerReady() {
  //設定開發版裝置連線
  boardReady('第一個裝置 ID', function (board) {
    board.systemReset();
    board.samplingInterval = 250;
    led1 = getLed(board, 10); //設定第一塊裝置的電燈接腳
    boardNum = boardNum + 1;
    if(boardNum===2){
      ready(); //裝置都上線後執行
    }
  });

  boardReady('第二個裝置 ID', function (board) {
    board.systemReset();
    board.samplingInterval = 250;
    led2 = getLed(board, 10); //設定第二塊裝置的電燈接腳
    boardNum = boardNum + 1;
    if(boardNum===2){
      ready(); //裝置都上線後執行
    }
  });

}

ready 流程最主要就是透過 .getCurrentTime() 抓取當下時間,然後每隔 0.1 秒就抓取一次時間,這樣就可以再差不多的時間觸發差不多的事情了。

function _a1(){
  led2.on();
  led1.off();
}

function _a2(){
  led1.on();
  led2.off();
}

function ready(){   
  player.playVideo();
  setInterval(function(){
   var sec = Math.round(player.getCurrentTime()*10)/10;
   if(sec>1.5 && sec<2){
     _a1();
   }else if(sec>3 && sec<3.5){
     _a2();
   }else if(sec>5 && sec<5.5){
     _a1();
   }else if(sec>6.3 && sec<7){
     _a2();
   }else if(sec>8 && sec<8.5){
     _a1();
   }else if(sec>9.5 && sec<10){
     _a2();
   }else if(sec>11.5 && sec<12){
     _a1();
   }else if(sec>13 && sec<13.5){
     _a2();
   }else if(sec>14.5 && sec<15){
     _a1();
   }else if(sec>16.5 && sec<17){
     _a2();
   }else if(sec>17.5 && sec<18){
     _a1();
   }else if(sec>19.5 && sec<20){
     _a2();
   }
  },100);
}

Webduino Youtube
(程式:http://bin.webduino.io/quhi/1/edit?html,js,output )

如果不想露臉或是露下巴,也可以改成開關,打開左邊的開關,左邊的燈就亮,打開右邊的燈,右邊的燈就亮。

Webduino Youtube

點選下面連結看影片比較有感覺:
https://www.youtube.com/embed/hGdarg7ZfiM

如果不太會寫程式也沒有關係,Webduino Blockly 線上編輯工具 ( https://blockly.webduino.io ) 也有提供近乎完整的 Youtube 功能讓大家使用,有興趣的也可以玩玩看。

Webduino Youtube



使用 HTML5 video

當然,純粹使用 HTML5 的 video tag 也是可以做到一樣的事情,下面這段程式,可以讓我們在透過 video 播放影片的時候,抓取影片當下的時間,如果再搭配上面的做法,就可以不用依賴 Youtube 也做出一模一樣的事情了。

<html>

<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>

<body>
  <video width="320" height="240" controls id="v" autoplay>
    <source src="r.mp4" type="video/mp4">
  </video>
  <script>
    var v = document.getElementById('v');
    setInterval(function(){
        console.log(v.currentTime);
    },1000);
  </script>
</body>

</html>

Webduino Youtube



小結

因為自己研究所是學多媒體與互動藝術的,當年要做出這種「影片 + 實際物品」的整合實在很困難,但現在隨著物聯網的技術進步,加上使用 Webduino 之後,輕輕鬆鬆就可以完成好幾件「錄像 + 互動」的作品,而且就算要寫程式也很簡單,不需要太高深的技巧,就可以做出很有趣的成果囉!( 突然好想用力的創作呀! )

參考:


上一篇
實戰智慧插座 22 - 用 Google Maps 開關燈 ( 燈泡互動篇 )
下一篇
實戰智慧插座 24 - 用 Opendata 開關燈 ( PM2.5 篇 )
系列文
Webduino 不只是物聯網,智慧插座也可以很 Modern~30

尚未有邦友留言

立即登入留言