WebページにYoutubeを埋め込む場合に、埋め込み用iframeのソースを張り付けるのが一般的です。特段にAPIを使う必要が無い場合にはYoutubeページにある埋め込み用iframeを張り付ければOKですね。例えばこんな感じのソースになります。
<iframe width="560" height="315" src="https://www.youtube.com/embed/P0qOt4LwmVc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
では、YoutubeのAPIを使う場合のメリットや恩恵は何なのでしょうか?Youtube iFrame Player APIと呼ばれるAPI(Application Programming Interface)をどのように使ったら良いのか一緒に見ていきましょう。実際に動作するソースコードも掲載しておきますので、詳しい使い方はこのページを参照してみてください。APIを使う必要が無いのであればこの記事は不要ですので読み飛ばしてしまってください。
Youtube iFrame APIを使うメリット
単にYoutubeの動画をWebページに表示したいのであれば、iFrame APIを使う必要はありません。先述のiFrameのソースコードをHTMLに張り付ければ万事OKです。「じゃあ、APIいらないじゃん」てなりますが、実はAPIを使えば詳細な機能を動画に付けることが可能になるんです。
Youtube iFrame Player APIを使うと動画に以下の機能を追加することが出来ます。
- 再生する動画の頭出し
- 動画の再生 / 一時停止 / 停止
- プレーヤーの音量の調節
- 再生中の動画に関する情報の取得
- 再生リスト内の動画の再生 / 次に送る / 前に戻る / シャッフル再生 など
- 再生速度率の設定
- 再生画質の指定
参考:iframe 組み込みの YouTube Player API リファレンス
JavaScriptのプログラムと組み合わせることで、ブラウザ内で再生のタイミングを変えたり、ストップさせたり出来ますね。プレイリストのシャッフル再生なんかも出来るのでオリジナルのプレイヤーみたいなものも作れます。動画の速度を変えたり、高画質動画を指定したりも出来るのでより複雑な挙動をYoutube動画に与えられます。
Youtube iFrame Player APIは無料で使える?
無料で利用出来ます。APIによっては有料のものもあるので不安になりますがこのiFrame APIは料金はかかりません。
余談ですが、APIが有料か無料かを判断する基準の一つに『「APIキー」が必要かどうか』を見れば分かる場合が多いので覚えておいて損はないです。
有料で料金がかかるものには必ずと言っていいほど「APIキー」を発行する手順を踏みます。これは、支払いとAPIの利用如何を紐づけるために必要で、APIキーが何回呼び出されたかによって、支払いの増減を図るという一手段になります。
APIキーを記載する必要があるAPIは無料か有料かを必ず確認しましょう。このYoutube iFrame Player APIにはAPIキーが必要ないので支払いと紐づけられることはありません。(Google MAPs API(Google Maps Platform)は課金制なのでAPIキーが必要ですね)
とりあえずAPIキーが必要ないから無料って考えればOKか
そもそも支払い方法と紐づけがないから請求されることはないですね
さあ、使ってみましょう
上のサンプル動画は、自動再生、音量0を指定しただけの単純な例になります。Youtube公式サイトのサンプルコードをさらに簡略化したものです。ソースコードは下記になります。
<div id="player"></div>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '431',
width: '784',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
event.target.setVolume(0);
event.target.playVideo();
}
JavaScriptの最初の4,5行は単にAPIのスクリプトを読み込んでいるだけですね。HTMLの<head>に書けるのであれば<head>に直書きしてしまってよいと思います。HTMLで書くと以下のようになりますね。
<script src="https://www.youtube.com/iframe_api"></script>
【Tips】自動再生が出来ない場合
Youtubeの動画のプレビュー画面は表示されるのに自動再生されない罠にハマることがあります。
原因は非常に単純で「必ず動画の音量が0かミュートされている」ことが必須条件になります。自動再生されて急に音が出てきたらビックリしますよね。たぶんGoogle側はそれを防ぐために音量をゼロに設定しないと自動再生が出来ない仕様にしたのだと思います。
上記サンプルだと以下の部分ですね。
function onPlayerReady(event) {
event.target.setVolume(0); // ←ここの部分が必須!音量注意!
event.target.playVideo();
}
上の関数はプレイヤーの準備が整った時の挙動をしていするスクリプトです。このonPlayerReady(event)
の最初に動画のボリュームをゼロにするという指定をしなくてはいけません。ちなみに下記でもOKです。
function onPlayerReady(event) {
event.target.mute(); // ←ミュートでも良いけどユーザーが音量調整できなくなることも……
event.target.playVideo();
}
event.target.mute()
の部分です。ただ、これだとスマホの機種によっては音量の調整が出来たり出来なかったりするようなので、オススメしません。動画の音を消す際はevent.target.setVolume(0);
で指定してあげる方が無難ですね。
【Tips】iPhone(Safari)への対応
自動再生されない現象はiPhoneのSafariでもハマることが多いです。
実機で検証したところ、先ほど記載したサンプルコードではiPhoneで再生が開始されませんでした。そこでいろいろ原因を探ったところ、実は自動再生に関してはevent.target.playVideo();
では上手くいかないことが分かりました。(なんでやねん)
埋め込みiframe同様に3つのパラメータをURLに渡してあげる必要があります。
- playsinline=1
- autoplay=1
- mute=1
これじゃ最初からiframe版使えばいいじゃんって突っ込みは置いておいて、これらに対応したコードを書くと下記のようになります。
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '431',
width: '784',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
},
playerVars: {
'loop': 1,
'playlist': movieID,
'playsinline': 1, // for iPhone
'autoplay': 1, // for iPhone
'mute': 1 // for iPhone
}
});
}
playerVarsにplaysinline,autoplay,muteをそれぞれ1(true)にして渡してあげればiPhoneでも自動再生がされるようになります。
1つの動画をループさせたい
APIで表示させた動画を永遠にループさせたい場合はどうしたらよいのでしょうか?
それにはplayerVars
というプロパティをコードに付与してあげる必要があります。playerVars
は動画のiframeのURLに付与するパラメーターをAPI版のJavaScriptで実装するものです。
通常、YoutubeのiframeのURLは以下のような形になります。
http://www.youtube.com/embed/P0qOt4LwmVc?enablejsapi=1&origin=http://example.com
例えばiframeのURLパラメータにloop=1
を付与したい場合にはAPIを利用すると下記のように記述します。
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '431',
width: '784',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
},
playerVars: { // YT.Playerの第二引数にplayerVarsパラメータを付与
'loop': 1 // パラメータ内のオブジェクトに'loop'の設定値を渡す
}
});
}
この記述を追加することにより、先ほどのiframeのURLに&loop=1
のパラメータが加えられます。
http://www.youtube.com/embed/P0qOt4LwmVc?loop=1&enablejsapi=1&origin=http://example.com
ただし、これだけだと動画がループされません。「Loop=1(true)にしてるんだから大丈夫でしょ」って思われますがこれまた落とし穴があるので注意が必要です。ひとつの動画をAPI経由でループさせるには下記2つのポイントを抑えなくてはなりません。
- playerVarsでloopを1に設定する
- playerVarsでplaylistを自身の動画ID(videoId)を指定する
上記を踏まえてコードを記載すると次のようになります。
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '431',
width: '784',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
},
playerVars: {
'loop': 1,
'playlist': 'P0qOt4LwmVc' // playlistをvideoIdと同一の値に指定する
}
});
}
このようにすることでiframeのURLにはloop=1
とplaylist=P0qOt4LwmVc
が付与され、http://www.youtube.com/embed/P0qOt4LwmVc?loop=1&playlist=P0qOt4LwmVc&enablejsapi=1&origin=http://example.comという形になり、1つの動画がループ再生されるようになります。
1つの動画のプレイリストをエンドレスに再生するっていうイメージですね。
複数の動画を再生できるようにしたい
Youtube公式のAPIサンプルでは1つの動画を再生するようにしか出来ないので、JavaScriptがよく分かってない方などは、いくつもコピペして動画のIDとコンテナのidを変えてソースコードが冗長になりがちです。
そこで公式のサンプルコードを少し変えて、なるべく短いコードで複数の動画を再生出来るように改修してみましょう。
おさらいですが、Youtube公式に掲載されているソースコードは以下になります。HTML側は、
<div id="player"></div>
と、動画表示するコンテナを用意してあげ、JavaScript側は
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
event.target.setVolume(0);
event.target.playVideo();
}
のように「APIの準備が整った時の関数(onYouTubeIframeAPIReady)」と「Youtube Playerの準備が整った時の関数(onPlayerReady)」を記述します。
しかし、これでは動画が増えるごとにonYouTubeIframeAPIReady()メソッドを増やしていってIDを変更しただけのソースコードがどんどん増えていってしまいますね。ソースコードが冗長になるのはメンテナンスにも悪影響を与えるのであまり賢いやり方ではありませんね。
このonYouTubeIframeAPIReady()という関数は公式ドキュメントによると
「ページでプレーヤー API 用の JavaScript のダウンロードが完了すると API がこの関数を呼び出します。これにより、ページで API を使用できるようになります。この関数では、ページが読み込まれたときに表示するプレーヤー オブジェクトを作成できます。」
https://developers.google.com/youtube/iframe_api_reference?hl=ja
とありますので、APIの準備が整ったタイミングで自動で発火します。ただ、この発火はAPIの読み込み完了後であればどのタイミングでも呼び出すことが可能なので以下のように書いても問題ありません。別の箇所で呼び出せるので引数を渡して(動画ID、HTMLのコンテナのID等)実行するのも一つの手です。
ただ、onYouTubeIframeAPIReady()は基本的に1度だけ発火させるのがYoutube公式的にもスマートかなと思いますので、今回は別の方法で行ってみましょう。参考までに下記はwindowがloadした後にonYouTubeIframeAPIReadyを呼び出すサンプルです。これでも動作します。
let player;
function onYouTubeIframeAPIReady(myMessage) {
console.log('onYouTubeIframeAPIReadyが発火しました');
console.log(myMessage);
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: 'P0qOt4LwmVc',
events: {
'onReady': onPlayerReady
}
});
}
function onPlayerReady(event) {
event.target.setVolume(0);
event.target.playVideo();
}
window.onload = function(){ // ページのロード完了後にonYouTubeIframeAPIReadyを呼び出すテスト
onYouTubeIframeAPIReady('別途呼び出しました');
}
Youtube公式のサンプルコードに少し手を加えてHTMLにYoutube表示用のコンテナ(<div id=”なんちゃら”></div>の部分)を追加するだけで、自動的にAPIがターゲットの要素に発火するJavaScriptにしてみました。
表示例は以下になります。3つの動画を1つのJavaScriptで使いまわしてHTML側で表示の制御をする効率的なコードです。とりあえず動画を見てみてください。それぞれ別の動画が表示されています。
早速ですが、全コードを掲載しておくのでご参考になさってください。(おそらくコピペでイケるかと思います)。
<script src="https://www.youtube.com/iframe_api"></script>
<div id="player-01" data-movid="P0qOt4LwmVc" class="yt-container"></div>
<div id="player-02" data-movid="6rUXIUkpQLE" class="yt-container"></div>
<div id="player-03" data-movid="1sCHGAro92g" class="yt-container"></div>
HTML側には任意のタグに「id」「data-movid」「class」を以下のルール通りに記述するだけです。
- id……player-01, player-02, player-03…のようにページ内で一意の値になるように指定
- data-movid……Youtube動画の動画IDを指定
- class……これは「yt-contaier」などのように全要素共通で保持するクラス名を指定。このクラス名でYoutubeの表示エリアであることを判別しています。
上記のルールさえ守れば動画が5個になろうが、10個になろうがJavaScript側を修正することなく、<div>タグの追加だけでYoutubeが表示されます。
肝心のJavaScript側のコードは下記になります。
let multiPlaers;
let doYTplayer = function (containerID, movieID) {
multiPlaers = new YT.Player(containerID, {
height: '431',
width: '784',
videoId: movieID,
events: {
'onReady': onPlayerReady
},
playerVars: {
'loop': 1,
'playlist': movieID
}
});
}
function onYouTubeIframeAPIReady() {
let ytContainers = document.querySelectorAll('.yt-container');
let containerID, movieID;
for (const singleContainer of ytContainers) {
containerID = singleContainer.id;
movieID = singleContainer.dataset.movid;
doYTplayer(containerID, movieID);
}
}
function onPlayerReady(event) {
event.target.setVolume(0);
event.target.playVideo();
}
特筆することもないですが、共通で使う関数を新しく作って引数で動画のIDとコンテナのIDを渡して実行しているだけですね。実際の核になる実行部分はdoYTplayer(containerID, movieID);
となります。containerIDやmovieIDはHTMLの各プロパティから引っ張ってきているので、JavaScriptを触る必要がなくなるところがポイントでしょうか。
ちなみに4つめの動画を表示させてみるには、
<div id="player-04" data-movid="hpTI-svzM-0" class="yt-container"></div>
とHTMLに記述するだけでOKです。以下のようにきちんと表示されます。
これでもうJavaScriptを触らなくてよくなりました。仕様変えるときは触りますけどね(笑)
まとめ
- Youtube iFrame Player APIを使うと単にiFrameで埋め込むより詳細な調整が可能
- Youtube iFrame Player APIは無料
- 自動再生出来ないときは、動画の音が出てしまっていないか確認
- ループ再生するときは自身の動画のみの再生リストを疑似的に作ってループ
- 動画を複数設置したい時はJavaScriptをいろいろカスタマイズして自分好みの仕様にしてみよう
以上になります。何かご質問等あればメールでもDMでもご連絡ください。無償の範囲でお答えします。あ、お仕事の依頼も歓迎です。