tekitoumemo’s diary

思ったことを書くだけ。長文版Twitter

ReactでYoutubeをテクニカルに扱う

https://www.tam-tam.co.jp/tipsnote/wpdata/wp-content/uploads/2014/04/6.YouTube-Player-API-690x362.jpg

ReactでIFrame Player APIを使う方法を軽く説明

IFrame Player APIって何かというとコレ↓を操作するAPIのことです。マシュメロの「Happier」です(今年一番おすすめ!)
youtu.be

全く使い道がなさそうなAPIですが、僕の場合は「音声のみ再生させたいなー」と思ったんで使ってみました。こんな感じになりました。
f:id:tekitoumemo:20181029220217p:plain

ReactでIFrame Player APIを使う場合はreact-youtubeというのを使います。ようはIFrame Player APIのwrapperです。
www.npmjs.com

インストール

npm i react-youtube

コンポーネント

<YouTube
  videoId={string}                  // defaults -> null
  id={string}                       // defaults -> null
  className={string}                // defaults -> null
  containerClassName={string}       // defaults -> ''
  opts={obj}                        // defaults -> {}
  onReady={func}                    // defaults -> noop
  onPlay={func}                     // defaults -> noop
  onPause={func}                    // defaults -> noop
  onEnd={func}                      // defaults -> noop
  onError={func}                    // defaults -> noop
  onStateChange={func}              // defaults -> noop
  onPlaybackRateChange={func}       // defaults -> noop
  onPlaybackQualityChange={func}    // defaults -> noop
/>

イベント毎にメソッドを指定すればいい感じです。

サンプル

import React from 'react';
import YouTube from 'react-youtube';
 
class Example extends React.Component {
  render() {
    const opts = {
      height: '390',
      width: '640',
      playerVars: { // https://developers.google.com/youtube/player_parameters
        autoplay: 1
      }
    };
 
    return (
      <YouTube
        videoId="2g811Eo7K8U"
        opts={opts}
        onReady={this._onReady}
      />
    );
  }
 
  _onReady(event) {
    // access to player in all event handlers via event.target
    event.target.pauseVideo();
  }
}

こんな感じっす。もう、まんま公式で申し訳ないのですがイベントと操作方法に関しては以下の公式サイトを
YouTube Player API Reference for iframe Embeds  |  YouTube IFrame Player API  |  Google Developers

playerVarsのパラメータは以下を参考にしてください。
YouTube Embedded Players and Player Parameters  |  YouTube IFrame Player API  |  Google Developers

一応上にないサンプルで、10秒早送りする場合

    var currentTime = event.target.getCurrentTime();
    event.target.seekTo(currentTime + 10);

Youtubeコンポーネント外で操作する
Jqueryなら以下のように利用出来ます。

var $playerWindow = $('#popup-YouTube-player')[0].contentWindow;
$playerWindow.postMessage('{"event":"command","func":"'+action+'","args":""}', '*');

ですが、ReactだとDom操作出来ないので(出来るけどダメ絶対)onReadyでStateにEventを入れて対応しました。

public _onReady(event: any) {
    this.setState({
        event: event
    });
}

onReadyは必ず通るので、Event入れてあとは使い回す方法です。これが良いのかどうかは不明。

音楽のみ再生する
これをやりたかったんですが、まともにやろうとするとめっちゃ違法で捕まるリスクがあります。以下に書いてありましたが、完全に違法ダウンロードです。やめましょう。
stackoverflow.com

ただ、YoutubeAPIを使って動画を再生させながら音源をダウンロードせずに流せば問題ないので色々試しました。

hiddenを使う
普通にHiddenを使うか、以下のように画面外に表示させて再生させます。

hidden{
    position:absolute;
    left:-10000px;
    top:-10000px;
    visibility:hidden;
}

が、これだと再生してくれません。IFrame Player APIでいうとずっとバッファリング中になってずっと再生されません。Youtubeはさすが対策してますね。

サイズを0にする
optsに渡すサイズを0にします。

  render() {
    const opts = {
      height: '0',
      width: '0',
      playerVars: { // https://developers.google.com/youtube/player_parameters
        autoplay: 1
      }
    };

これは再生できました。

iPhonesafariか不明)では、再生してくれません。XCodeのシュミレーターでも再現するので試す人は確認してみてください。

Youtube天才かよ。。

なので、音声のみは再生出来ません。あきらめましょう。

諦めきれないのでまだ試します。

サイズを1にする
optsに渡すサイズを1にします。

  render() {
    const opts = {
      height: '1',
      width: '1',
      playerVars: { // https://developers.google.com/youtube/player_parameters
        autoplay: 1
      }
    };

これは、iPhoneでも再生されます。当たり前ですね、動画を再生しているのですから。

もちろん、Youtubeではバックグラウンド再生が出来ないので画面遷移したら音楽が止まります。そこは潔くあきらめましょう。Audioタグはバックグラウンドでも再生出来るのですが、MP3などの音源を使わなければいけないので日本では使い物にならないですね。

普通に使うならreact-youtubeなんて必要ないですが、ちょっと小細工してみたい人がいたら使ってみてはいかがでしょうか。

Reactはこういうwrapperがたくさんあるのでかなり使いやすいですね。Jqueryで頑張っちゃったときの罪悪感がないのも素敵!