jquery audio.js を使ってみる

2013年11月22日

音楽(MP3)を再生する必要があったので、探していたら「 audio.js」が見つかったのでその使い方のメモ。

ダウンロード

以下の「audio.js」のページからダウンロード
http://kolber.github.io/audiojs/

解凍して、「audiojs」フォルダ(audio.min.js, player-graphics.gif audiojs.swf が入っている)を適当なところに配置。

ドキュメント

以下のリンクに英語のドキュメントがある
http://kolber.github.io/audiojs/docs/

インストール

配置した audio.min.js を読み込む

<script src="../audiojs/audio.min.js"></script>

audio.js を初期化して使用できるようにする。

<script>
  audiojs.events.ready(function() {
    var as = audiojs.createAll();
  });
</script>

プレイヤー(再生バー)を設置したい所(HTML)に audio タグを記述

<audio src="/mp3/juicy.mp3" preload="auto" />

src には再生したい音声ファイルのパスを指定。
preload=”auto” :ページの読み込み時に自動的に音声ファイルも読み込み開始
preload=”none” :再生ボタンを押してから読み込みを開始

基本的にはこれで src に指定した音声ファイルを再生可能。

プレイヤー(再生バー)のカスタマイズ

「audio.min.js」により自動的に CSS(style 要素)が head 要素の先頭に挿入されるので、その後に CSS の値を上書きすると見た目を変更できる。

サンプルの「Customised player」を参考にして変更した例。

<style>
      /* プレイヤー(再生バー)の高さ、幅、背景色の指定 */
      .audiojs { height: 22px; background: #404040; width: 280px;}
      /* 再生・停止ボタンの高さ、幅、パディングの指定 */
      .audiojs .play-pause { width: 25px; height: 20px; padding: 0px 8px 0px 0px; }
      /* 再生・停止ボタンなどの p 要素 */
      .audiojs p { width: 25px; height: 20px; margin: -3px 0px 0px -1px; }
      /* 進行状態・ロードの状態を表示する部分 */
      .audiojs .scrubber { background: #5a5a5a; width: 150px; height: 10px; margin: 5px; }
      /* 進行状態を表示するバーの部分 */
      .audiojs .progress { height: 10px; width: 0px; background: #ccc; }
      /* ロード状態を表示するバーの部分 */
      .audiojs .loaded { height: 10px; background: #000;}
      /* 再生時間の部分 */
      .audiojs .time { float: left; height: 25px; line-height: 25px; }
      .audiojs .error-message { height: 24px;line-height: 24px; }
       /* 再生している曲の情報 */
      .track-details { clear: both; height: 20px; width: 280px; padding: 1px 6px; background: #eee; color: #222;  font-size: 11px; line-height: 20px;}
      .track-details:before { content: '♬  Now Playing: '; }
    </style>

「audio.min.js」により挿入される HTML 要素の例

<div class="track-details" style="">曲名</div>
<div id="audiojs_wrapper0" class="audiojs " classname="audiojs" style="">
    <audio preload="auto" src="xxxx/01.mp3"></audio>
    <div class="play-pause">
        <p class="play"></p>
        <p class="pause"></p>
        <p class="loading"></p>
        <p class="error"></p>
    </div>
    <div class="scrubber">
        <div class="progress" style="width: 5.4779px;"></div>
        <div class="loaded" style="width: 150px;"></div>
    </div>
    <div class="time">
        <em class="played">00:02</em>
        /
        <strong class="duration">00:58</strong>
    </div>
    <div class="error-message"></div>
</div>

プレイリストの作成例

サンプルの「 Customised playlist player」を参考にプレイリストを作成した例。

概要

  • 以下の様な div.cd に囲まれたリストが複数ある
  • 最後の li 要素には「last」というクラスを付けておく
  • 「data-src」属性に再生する曲の音声ファイルのパスを指定
  • プレイヤー(再生バー)は最初は非表示
  • リストのリンクをクリックするとプレイヤー(再生バー)を表示して音楽を再生
  • その際に li 要素のテキスト(曲名)を「.track-details」に表示
  • 次の曲がある場合(リストの最後でなければ)次の曲を再生
  • 次の曲がなければ(リストの最後なら)停止して、プレイヤー(再生バー)を非表示にする
・・・省略・・・
<div id="contents">
  <h2>CD</h2>
  <audio preload="auto"></audio>  //プレイヤー(再生バー)
  <div class="track-details"></div>   //曲名を表示
・・・省略・・・

<div class="cd">
    <ol>
        <li><a href="#" data-src="01.mp3">Song 1</a></li>
        <li><a href="#" data-src="02.mp3">Song 2</a></li>
        <li><a href="#" data-src="03.mp3">Song 3</a></li>
        ......  
        <li class="last"><a href="#" data-src="03.mp8">Song 8</a></li>     
    </ol>
</div><!-- end of .cd -->

<div class="cd">
    <ol>
        <li><a href="#" data-src="a.mp3">Song a</a></li>
        <li><a href="#" data-src="b.mp3">Song b</a></li>
        <li><a href="#" data-src="c.mp3">Song c</a></li>
        ......  
        <li class="last"><a href="#" data-src="h.mp8">Song h</a></li>     
    </ol>
</div><!-- end of .cd -->

・・・省略・・・
</div><!--end of #contents-->
・・・省略・・・

jQuery

jQuery(function($){
    var clicked;  //クリックされた li 要素を格納する変数
    var a = audiojs.createAll({
        //曲が終了した時の処理
        trackEnded: function() {
            //クリックして再生した曲の li 要素のクラスが「last」の場合、終了して非表示に
            if($('ol li.playing', clicked.closest('div.cd')).hasClass('last')){
                $('div.audiojs, div.track-details').fadeOut('slow');
                $('ol li.playing').removeClass('playing');
                return;
           }
           //次の曲を設定
           var next = $('ol li.playing', clicked.closest('div.cd')).next();
           if (!next.length) next = $('ol li', clicked.closest('div.cd')).first();
           next.addClass('playing').siblings().removeClass('playing');
           //曲名を「div.track-details」に表示
           $('div.track-details').html(next.closest('li').text());
           //プレイヤー(再生バー)をリストの後に追加(appendTo)して表示
           $('div.audiojs, div.track-details').appendTo(next.closest('div')).fadeIn('slow');
           //プレイヤーをリストの直後に入れる場合はinsertAfterで
           //$('div.audiojs, div.track-details').insertAfter(next.closest('div').find('ol')).fadeIn('slow');
           //曲を再生
           audio.load($('a', next).attr('data-src'));
           audio.play();
        }
    });
        
    // 最初の曲をロード
    var audio = a[0];
    first = $('ol a').attr('data-src');
    $('ol li').first().addClass('playing');
    audio.load(first);
    
    // プレイヤー(再生バー)と曲の情報は最初は非表示に  
    $('div.audiojs, div.track-details').css('display', 'none');

    //クリックされた曲をロードして再生
    $('ol li').click(function(e) {
        clicked = $(this);
        e.preventDefault();
        $('div.track-details').html($(this).closest('li').text()).appendTo($(this).closest('div')).fadeIn('slow');  
        $('div.audiojs, div.track-details').appendTo($(this).closest('div')).fadeIn('slow');
         //プレイヤーをリストの直後に入れる場合
         //$('div.audiojs, div.track-details').insertAfter(next.closest('div').find('ol')).fadeIn('slow');
        $(this).addClass('playing').siblings().removeClass('playing');
        audio.load($('a', this).attr('data-src'));
        audio.play();
    });
});

モダンブラウザでは上記で問題なく再生されるが、IE7、IE8 ではプレイヤー(再生バー)は表示されるが、音楽が再生されない。コンソールを確認すると、以下の様なエラーが表示されていた。

SCRIPT16389: 名前が不明です。
xxxxx.html, 行 49 文字5

SCRIPT16389: 未定義のエラーです。
xxxxx.html, 行 49 文字5

「行 49 文字5」を見ても原因はまったくわからない。切り分けてみたところ、「div.audiojs」を「appendTo」する処理があるとこのエラーが出ることがわかったが、原因は不明。

$('div.audiojs').appendTo($(this).closest('div'));  //これがエラーの原因?

追加情報

2013年12月15日
エミュレータでは、なんとかなったかのように見えたが、実機で IE8 で試してみると、表示がくずれてしまい、またそもそもエラーで作動しなかったので諦めて、代わりに「jPlayer (2.5.0)」を使うことにしました。

関連ページ:「jPlayer (2.5.0) を使ってみる

したがって以下の部分は、参考にしないでください(自分用のメモとして残しておきます)。

また、解決策は見つからなかったので、最後の手段としてブラウザ判定して、IE7、IE8 ではそれぞれのリストの下にプレイヤーを表示するのはあきらめて常にページの固定した場所に表示するようにした。

以下は現時点での例。

jQuery(function($){      
    var _ua = (function(){  //ブラウザ判定
        return {
            ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
            ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
            ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined"
        }
    })();
  
    if(!_ua.ltIE8){  //モダンブラウザ   
        var clicked;
        var a = audiojs.createAll({
            trackEnded: function() {
                if($('ol li.playing', clicked.closest('div.cd')).hasClass('last')){
                    $('div.audiojs, div.track-details').fadeOut('slow');
                    $('ol li.playing').removeClass('playing');
                    return;
                }
                var next = $('ol li.playing', clicked.closest('div.cd')).next();
                if (!next.length) next = $('ol li', clicked.closest('div.cd')).first();
                next.addClass('playing').siblings().removeClass('playing');
                $('div.track-details').html(next.closest('li').text());
                $('div.audiojs, div.track-details').appendTo(next.closest('div')).fadeIn('slow');
                audio.load($('a', next).attr('data-src'));
                audio.play();
            }
        });
        
        // Load in the first track
        var audio = a[0];
            first = $('ol a').attr('data-src');
        $('ol li').first().addClass('playing');
        audio.load(first);
    
        $('div.audiojs, div.track-details').css('display', 'none');

        // Load in a track on click
         $('ol li').click(function(e) {
                clicked = $(this);
                e.preventDefault();
                $('div.track-details').html($(this).closest('li').text()).appendTo($(this).closest('div')).fadeIn('slow');  
                $('div.audiojs, div.track-details').appendTo($(this).closest('div')).fadeIn('slow');
                $(this).addClass('playing').siblings().removeClass('playing');
                audio.load($('a', this).attr('data-src'));
                audio.play();
        });
    }else{
        //IE7、IE8
        var clicked;
        var a = audiojs.createAll({
        trackEnded: function() {
            if($('ol li.playing', clicked.closest('div.cd')).hasClass('last')){
                $('ol li.playing').removeClass('playing');
                return;
            }
            var next = $('ol li.playing', clicked.closest('div.cd')).next();
            if (!next.length) next = $('ol li', clicked.closest('div.cd')).first();
            next.addClass('playing').siblings().removeClass('playing');
            $('div.track-details').html(next.closest('li').text());
            audio.load($('a', next).attr('data-src'));
            audio.play();
          }
        });
        
        // Load in the first track
        var audio = a[0];
            first = $('ol a').attr('data-src');
        $('ol li').first().addClass('playing');
        $('div.track-details').html($('ol li').first().text());
        audio.load(first);

        // Load in a track on click
        $('ol li').click(function(e) {
            clicked = $(this);
            e.preventDefault();
            $('div.track-details').html($(this).closest('li').text());  
            $(this).addClass('playing').siblings().removeClass('playing');
            audio.load($('a', this).attr('data-src'));
            audio.play();
        });
    }
});

IE7、IE8 用の記述はサンプルの「 Customised playlist player」とほぼ同じ内容。

ブラウザの判別のコードは「JavaScript ユーザエージェント条件分岐便利スニペット(W3G)」を参考にさせていただきました。

以下は上記を変更(改良)した例:

  • track-details と audiojs を一定の順序で表示
  • どの位置でもプレーヤーが見えるように必要であればスクロールして表示
  • プレーヤーを閉じるボタンを追加
jQuery(function($){        
    var _ua = (function(){  //ブラウザ判定
        return {
            ltIE6:typeof window.addEventListener == "undefined" && typeof document.documentElement.style.maxHeight == "undefined",
            ltIE7:typeof window.addEventListener == "undefined" && typeof document.querySelectorAll == "undefined",
            ltIE8:typeof window.addEventListener == "undefined" && typeof document.getElementsByClassName == "undefined"
        }
    })();
  
   //閉じるボタンをクリックした際の処理 
  $(document).on('click', '.close_audio', function() { 
    audio.pause();
    $('div.audiojs, div.track-details').fadeOut('slow');  
  });
  
  if(!_ua.ltIE8){     
    var clicked;
    var a = audiojs.createAll({
      trackEnded: function() {
        if($('ol li.playing', clicked.closest('div.cd')).hasClass('last')){
          $('div.audiojs, div.track-details').fadeOut('slow');
          $('ol li.playing').removeClass('playing');
          return;
        }
        var next = $('ol li.playing', clicked.closest('div.cd')).next();
        if (!next.length) next = $('ol li', clicked.closest('div.cd')).first();
        next.addClass('playing').siblings().removeClass('playing');
        //閉じるボタンを追加
        $('div.track-details').html(next.closest('li').text() + '<p class="close_audio"><span class="glyphicon glyphicon-remove-circle"></span> close </p>');
        //track-details と audiojs を一定の順序で表示
        $('div.track-details').insertAfter($(this).closest('div').find('ol'));
        $('div.audiojs').insertAfter($(this).closest('div').find('ol'));
        $('div.audiojs, div.track-details').fadeIn('slow');
        audio.load($('a', next).attr('data-src'));
        audio.play();
      }
    });
        
    // Load in the first track
    var audio = a[0];
    first = $('ol a').attr('data-src');
    $('ol li').first().addClass('playing');
    audio.load(first);
    
    $('div.audiojs, div.track-details').css('display', 'none');

    // Load in a track on click
    $('ol li').click(function(e) {
      $('div.audiojs, div.track-details').css('display', 'none');
      clicked = $(this);
      e.preventDefault();
      //閉じるボタンを追加
      $('div.track-details').html($(this).closest('li').text() + '<p class="close_audio"><span class="glyphicon glyphicon-remove-circle"></span> close </p>').appendTo($(this).closest('div'));        
      //track-details と audiojs を一定の順序で表示
      $('div.track-details').insertAfter($(this).closest('div').find('ol'));
      $('div.audiojs').insertAfter($(this).closest('div').find('ol'));
      $('div.audiojs, div.track-details').fadeIn('slow');      
      $(this).addClass('playing').siblings().removeClass('playing');
      
      //どの位置でもプレーヤーが見えるように必要であればスクロールして表示
      if($('div.audiojs:first').offset().top > ($(window).scrollTop() + $(window).height())) {
        var window_bottom_y = $(window).scrollTop() + $(window).height();
        var audiojs_offset_y = $('div.audiojs:first').offset().top - window_bottom_y;
        var window_top = $(window).scrollTop() + audiojs_offset_y + 80;
        $('body,html').animate({
          scrollTop: (window_top)
        }, 500);
      }      
      audio.load($('a', this).attr('data-src'));
      audio.play();
    });
  }else{
        //IE7、IE8
        var clicked;
        var a = audiojs.createAll({
        trackEnded: function() {
            if($('ol li.playing', clicked.closest('div.cd')).hasClass('last')){
                $('ol li.playing').removeClass('playing');
                return;
            }
            var next = $('ol li.playing', clicked.closest('div.cd')).next();
            if (!next.length) next = $('ol li', clicked.closest('div.cd')).first();
            next.addClass('playing').siblings().removeClass('playing');
            //閉じるボタンを追加
            $('div.track-details').html(next.closest('li').text() + '<p class="close_audio"><span class="glyphicon glyphicon-remove-circle"></span> close </p>').appendTo($(this).closest('div'));
            audio.load($('a', next).attr('data-src'));
            audio.play();
          }
        });
        
        // Load in the first track
        var audio = a[0];
            first = $('ol a').attr('data-src');
        $('ol li').first().addClass('playing');
        $('div.track-details').html($('ol li').first().text());
        audio.load(first);

        // Load in a track on click
        $('ol li').click(function(e) {
            clicked = $(this);
            e.preventDefault();
            //閉じるボタンを追加
            $('div.track-details').html($(this).closest('li').text() + '<p class="close_audio"><span class="glyphicon glyphicon-remove-circle"></span> close </p>').appendTo($(this).closest('div'));  
            $(this).addClass('playing').siblings().removeClass('playing');
            audio.load($('a', this).attr('data-src'));
            audio.play();
        });
    }
});

CSSに以下を記述

.close_audio {
  cursor: pointer;
}