LoginSignup
55

More than 3 years have passed since last update.

動画をwebに実装するときのメモ(video, youtube API, vimeo API)

Last updated at Posted at 2017-12-28

動画をwebに実装するときのメモ

動画の実装に馴染みがなかったので浅く調べたメモとAPIなど各実装時のパラメーターやイベントのまとめや複数設置や実装してみてわかったメモ

特徴

video 要素

メリット

  • コンテンツの一元管理ができる
  • 自由なサイズで埋め込み可能

デメリット

  • 自前のサーバーに置くので負荷の心配

Youtube

メリット

  • 自前のサーバーに依存しない
  • 共有性が高い
  • youtubeからや共有先などからの流入経路に期待が持てる
  • SEOに強い(動画単体でインデックスされるので検索で動画の方が上位表示されることもある)

デメリット

  • 意図せぬユーザーからのコメント等
  • サーバーが自前じゃ無いから不慮の事態(動画だけ遅いとか)の復旧等はプラットフォーム依存
  • 停止状態の時の「youtube」のロゴだけはどうやっても消せない

※静止した時にyoutubeのサムネイルではなくオリジナルのサムネイルを用意してかぶせて隠して回避する

  • 比率が一定なので縦長い動画を設置したい時、横に黒いふちがつく(サイト上の埋め込み時はサイズ指定で解消する)

※ちなみにあの黒い縁はウインドウボックスと言うらしい
https://support.google.com/youtube/answer/118277?hl=ja

※Youtubeの埋め込みiframeは複数設置の場合、インラインでミュート設定しても同時自動再生はできないのでやりたい場合はIFrame Player APIを使う

vimeo

メリット

  • 自前のサーバーに依存しない
  • 動画コントローラーのカスタマイズ性が高い
  • 自由なサイズで埋め込み可能

デメリット

  • インライン再生ができない(iOS Safariで自動再生はできない)
  • サーバーが自前じゃ無いから不慮の事態(動画だけ遅いとか)の復旧等はプラットフォーム依存

基本メモ

レスポンシブ対応とアスペクト比固定

html
<div class="video-wrap">
    <video id="video01" loop muted playsinline>
        <source src="./video/01.mp4" type="video/mp4" />
    </video>
</div>
scss
.video-wrap {
  position: relative;
  width: 100%;// デザインにより調整
   &:before {
    content: "";
    display: block;
    width: 100%;
    padding-top: 56.25%;// =高さの比率(9) / 幅の比率(16) *100% (※オリジナルの比率の場合は高さ / 幅 * 100%)
  }
  #video01 {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}

iOS10以降対応自動再生

条件は

  • インライン再生であること
  • 無音状態(ミュート)であること
html
<video id="video01" loop muted playsinline>
    <source src="./video/01.mp4" type="video/mp4" />
</video>

参考
iOS10 Mobile Safariにおけるビデオの自動再生

iOS10よりバージョンが低い場合
Safari HTML5 Audio and Video Guide
User Control of Downloads Over Cellular Networks部分参照

In Safari on iOS (for all devices, including iPad), where the user may be on a cellular network and be charged per data unit, preload and autoplay are disabled. No data is loaded until the user initiates it. This means the JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. In other words, a user-initiated Play button works, but an onLoad="play()" event does not.

携帯電話回線での閲覧は通信容量を消費するので課金されちゃうからユーザーに無断でのDLは推奨してしないんでユーザーがアクション起こさないと押さないと再生させないからね!(意訳)

*自動再生が可能になったといって、ユーザビリティを考えると乱用はおすすめしません。

中国での規制

youtube、viemo等は中国で規制されているので、ローカライズが必要なサイトには向かず、実装した場合、極端にサイトの読み込みが遅くなるか表示されないらしい。

中国のネット検閲:Wikipedia

IEでz-indexが効かない(youtube)

オリジナルのサムネイルを作成し動画の上にかぶせる場合などで発生するのでwmode=transparentを付与して対応する

埋め込みiframeの場合
<iframe src="http://www.youtube.com/embed/動画ID?wmode=transparent"></iframe>
iframePlayerApiの場合
var player = new YT.Player(id, {
    ~ 中略 ~
    playerVars: {
        wmode : "transparent"
    }
});

参考:
Youtubeでもz-indexが効くようにする「?wmode=transparent」パラメーターをjQueryで自動挿入する
レガシーIEでのYouTube(iframe)対応

基本実装

共通前提:インライン、ミュート、自動再生。jsはjquery使用
複数の場合の前提:同上 + 並べて順番に再生

※メモリやらCPUやら通信容量やらをくっちゃうので延々流すのはよろしくないですが、こういう案件があったので><

video 要素

パラメータは要素に付与する
参考:video 要素

単体

html
<video id="player" autoplay loop muted playsinline width="100%">
    <source src="./video/hoge.mp4">
</video>

複数設置

html
<video id="player01" autoplay muted playsinline width="100%">
    <source src="./video/hoge01.mp4">
</video>

<video id="player02" muted playsinline width="100%">
    <source src="./video/hoge02.mp4">
</video>
js
$(function () {
    $('#player01').on('ended', function () {// player01終了
        $('#player02').get(0).play();
    });

    $('#player02').on('ended', function () {// player02終了
        $('#player01').get(0).play();
    });
});

上記を元に必要な処理を入れていく

例:全部で5回ループしたら終了
$(function () {
    var cnt = 0;

    $('#player01').on('ended', function () {// player01終了
        cnt++;
        if (cnt < 5) {// 全てのループは5回まで
            $('#player02').get(0).play();
        } else {
            $('#player01').get(0).autoplay=false;
            //console.log('全ループ終わったよ');
        }
    });

    $('#player02').on('ended', function () {// player02終了
        $('#player01').get(0).play();
    });
});

多くなったらまとめちゃう

配列苦手なので自分用メモ
$(function () {
    for (var i = 1; i <= 2; i++)
    {
        (function() {
            var videoIndex = (i != 2) ? (i + 1) : (1);
            var next = $("#player0" + videoIndex);

            $("#player0" + i).on("ended", function() {
                next.get(0).play();
            });
        })(i);
    }
});

endedやseekedなど状態を取得するイベントが用意されてる
参考:video要素、audio要素をJavaScriptから操作する

youtube

iframe player api使用

単体

html
<div id="player"></div>
js
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 ytPlayer;

function onYouTubeIframeAPIReady() {
    ytPlayer = new YT.Player('player', {
        height: 390,
        width: 640,
        videoId: 'vifZUxk2WgI',
        playerVars: {//パラメータ
          playsinline: 1,// インライン再生指定
          rel      : 0,// 再生中の動画と同じチャンネルの関連動画を表示
          controls: 0,// コントローラー出さない
          showinfo: 0// タイトルとか動画情報出さない
        },    
        events: {// イベント
            'onReady': onPlayerReady
        }
    });
}

function onPlayerReady() {
  ytPlayer.mute();// ミュートにしてから
  ytPlayer.playVideo();// 再生
}

onStateChangeで状態取得する時のサンプルは下記
サンプル:CodePen

複数

html
<div id="player"></div>
<div id="player1"></div>
js
// 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);

var ytPlayer, ytData, ytPlaying, ytStop, ytPlay;

ytPlayer = [];
ytData = [// 呼び出したい動画と表示したい箇所のIDを設定
  {id: 'hEkexHJJdHc', area: 'player'},
  {id: 'L6ZrKPMzOmg', area: 'player1'}
];

function onYouTubeIframeAPIReady() {
  for(var i = 0; i < ytData.length; i++) {
    ytPlayer[i] = new YT.Player(ytData[i]['area'], {
      videoId: ytData[i]['id'],
      playerVars: {
        playsinline: 1,// インライン再生指定
        rel      : 0,// 再生中の動画と同じチャンネルの関連動画を表示
        controls: 0,// コントローラー出さない
        showinfo: 0// タイトルとか動画情報出さない
      }  ,    
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      }
    });
  }  
}

function onPlayerReady(e) {
  ytPlayer[0].mute();
  ytPlayer[0].playVideo();//1個目の動画を再生
}

function onPlayerStateChange(e) {
  var state, target;
  state = e.target.getPlayerState();
  target = e.target.getIframe().id;
  if(state == 0) {// 終了した時
    ytPlayer[1].mute();
    ytPlayer[1].playVideo();//2個目の動画を再生
  }
}

パラメータ:YouTube 埋め込みプレーヤーとプレーヤーのパラメータ
イベント:IFrame Player API イベント
※targetでプレイヤー識別可能。複数ある場合はgetIframeでid取得して識別
※onReady以外はgetPlayerStateで状態を取得できる。

onStateChangeで状態取得するサンプルと再生終了したら次の動画を再生するサンプルは下記
サンプル:CodePen

よく使いそうなイベント
  • onReady 読み込み完了
  • onStateChange プレイヤーの状態が変わった時
  • onError プレイヤーがエラーになった時 など

vimeo

vimeo API使用。
インライン再生にするパラメータが無い(見つからなかった)ので前提からインライン再生を除く
共通前提:ミュート、自動再生(iOS safari以外)
複数の場合の前提:同上 + 並べて順番に再生

※ある程度再生したら勝手に止まるようなので延々流したかったら(やらない方がいいですが)工夫が必要

単体

html
<div id="player"></div>
(中略)
<script src="//player.vimeo.com/api/player.js"></script>
js
$(function() {
    // プレーヤーのオプション設定
    var options = {
        id: 198853598, // VimeoのID
        autoplay: true, // 自動再生
        byline: false, // 投稿者の表示
        portrait: false, // Vimeoロゴの表示
        color: 'ff0000', // プレーヤーのカラー        
        title: false // 動画タイトルの表示
    };

    var player = new Vimeo.Player($('#player'), options);

    player.setVolume(0); // ミュート
    player.play();// 再生
});
データ属性でオプション設定も可能
<div id="player" data-vimeo-id="198853598" data-vimeo-autoplay="true" data-vimeo-byline="false" data-vimeo-portrait="false" data-vimeo-color="ff0000" data-vimeo-title="false"></div>

複数

html
<div id="player01"></div>
<div id="player02"></div>
js

$(function() {
    // プレーヤーのオプション設定
    var options = {
        id: 198853598, // VimeoのID
        autoplay: true, // 自動再生させる
        byline: false, // 投稿者の表示
        portrait: false, // Vimeoロゴの表示     
        title: false, // 動画タイトルの表示
        autopause: true// 他のプレーヤーを一時停止にするかどうか
    };
    var options2 = {
        id: 203299850, // VimeoのID
        autoplay: false, // 自動再生させないでplayer01の再生終了をトリガーにする
        byline: false, // 投稿者の表示
        portrait: false, // Vimeoロゴの表示     
        title: false, // 動画タイトルの表示
        autopause: true// 他のプレーヤーを一時停止にするかどうか
    };

    var player01 = new Vimeo.Player($('#player01'), options);
    var player02 = new Vimeo.Player($('#player02'), options2);

    player01.setVolume(0); // ミュート
    player01.play();
    console.log('player01再生中1回目');

    player01.on('ended', function(data) {// player01を最後まで再生した時
        player02.setVolume(0);
        player02.play();
        console.log('player02再生中');
    });

    player02.on('ended', function(data) {// player02を最後まで再生した時
        player01.setVolume(0);
        player01.play();
        console.log('player01再生中');
    });
});

パラメータ:Vimeo Player API -> Embed Options
イベント:Vimeo Player API -> Events
メソッド:Vimeo Player API -> Methods

Vimeo複数サンプル:CodePen

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55