RSS

初出:2012年6月19日 00:35

日々、iPhoneやiPad、iTunesで再生した曲を「本日のiTunes BGM」としてブログに載せてた。2007年初頭から続けているんだが、実はこの仕組み、iTunesから書きだしたXMLをJavaScriptで解析してページに表示するということをやっていました。

KenG Weblog - はじめてのAjax:mixiミュージックもどきをブログで実現

でも、この方法だとデータによっては曲のリリース年が正しく表示されないという問題を抱えていたので、JavaScriptをやめてPHPで解析する方法に変えてみました。

参考にしたWebページはこちら。
PHPで書かれたiTunesのXMLパーサー

ポイントは、iTunesのXMLをパースすることに特化したPHPライブラリ「iTunes XML Parser for PHP」を使うこと。これが意外に簡単にできた。リリース年をきちんと表示できるようにすることが重要だったわけだけど、iTunes内の曲データにはリリース年が登録されていないものも多々ある。そういうものはいっそのこと曲そのものを表示しないという潔い仕様にすべく、パースしたHTMLをjQueryで判定して、非表示処理する自作ルーチンも組み込んでみた。

2007年に書いた先のブログでは、締めにこういうことを書いていた。

"曲リストにアフェリエイトのリンクを自動で張れたらいいなあ。iTunes StoreがAPIを公開してくれたら、そういったこともできるのにね。もしくはiTunes Storeの商品データベースをもっている他サイトが、そういう技術を提供するとか、してくれないかな。"

なんとそのとおりの技術があるというのだ。月日が流れるというのは伊達じゃない。その間、まったくノーチェックだったのは情けない。

iTunes Search APIから、視聴プレイヤーつきのアフィリエイトを作る

PHPでパースした曲データをiTunes Store APIに渡して、iTunesで扱っている曲だけを表示するようにしてみた。ここでのポイントは、曲名とアーティスト名と収録アルバム名の3つを組み合わせてAPIに問い合わせること。トッド・ラングレンの「Hello, It's me」は当然ながら「Something/Anything」に入っているわけで、ソフィア・コッポラには悪いが「ヴァージン・スーサイズ」の映画サントラが表示されても困る。でも「Something/Anything」のスラッシュをそのままAPIに渡すとうまく検索されないので、スラッシュを「+」に変換する細かい処理なんかを追加してある。

このAPIは、ジャケットのアートワークやiTunes Storeのリンク、さらには試聴音源のURLまで返してくれる。

http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/wsSearch?term=Two+Weeks+Grizzly+Bear+Veckatimest&country=jp&media=music&entity=musicTrack

そこで、今までの「本日のiTunes BGM」にはなかったアートワーク表示をしてみた。うーん、良い。じゃあさらに欲を出して、アートワークをクリックすると試聴できるようにしたい。ブラウザの互換性云々は気にもせず、HTML5のaudioタグでもって再生する処理を組んでみた。

参考にしたWebページはこちら。
HTML5 Audio オブジェクトを JavaScript で制御する方法

この参考サイトではブラウザ判定など、きちんとしたオーディオプレーヤー的なものを作っているが、自分はそこまで力を入れることもなく、必要最低限の処理に絞り込んだ。

その代わり、アートワークをクリックして再生/停止をする処理や、再生中に別の曲をクリックされた場合の動き。さらには、クリックしてから再生するまでのロード中にくるくるスピナーを表示させ、再生が終わったら停止ボタンを非表示にするというaudioタグのイベント制御に力を入れた(というか、UIをそうしちゃったからには力を入れざるを得なかった)。そこで、イベントを補足する方法はこのページを参考にした。
video/audio要素のイベントを捕捉する

そんなわけで一応完成したのが、このブログの全ページに表示されているiTunes BGM。これからIEなどのブラウザ対応やら、iPhone/iPadへの対応などやっていかないといけないけど、それはまた追々。

最後に。ただテキストで曲の情報を掲載しているよりも、アートワークがあったほうがより音楽が伝わるだろう。アートワークだけでなく、その場で曲を聴けたほうが音楽は当然グっと近くなるだろう。そう考えながら機能を追加してきたけど、ここまで作り切ったときにフと客観的に思ったのが、音楽だけでは何か足りない。曲を推薦している人がなぜこの音楽を選んだのか、その言葉を知りたい。そんな思いに駆られた。昨今では音楽評論家という職業がなかなか成り立たなくなっているという。権威化した評論家は鬱陶しいだけだが、リスナーをガイドしてくれる評論家は、大切だと思う。自分が評論家になれるとは思わないが、フランクな形で「この曲はお薦めだよ!」という意思表示はしていきたいなぁ。

JavaScriptはこちら(要jQuery)

https://wonderwall.net/blog/keng/itsplay.js (UTF-8です)

MovableTypeテンプレートに埋め込んだパーツは以下の内容。

<script src="/blog/keng/itsplay.js"></script>
<div id="TodaysBGM">
<h4 class="TodaysBGMBanner">本日のBGM</h4>
<p class="caption">曲名をクリックするとiTunes Storeで試聴できます。</p>
<?php
include "/www/htdocs/blog/keng/itunes_xml_parser_php5.php";
$songs = iTunesXmlParser("/www/htdocs/blog/keng/itunes.xml");
// if it worked
if ($songs)
{
// create a table
$output = '<ul id="myitunes">';
// loop through the songs in the array and get 4 fields that I want to see
foreach ($songs as $song)
{
$output .= '<li class="item clearfix">';
$output .= '<div class="artwork"></div>';
$output .= '<div class="title"><span class="song">'.$song["Name"].'</span>';
$output .= '<div class="info clearfix"><span class="artist">'.$song["Artist"].'</span>';
$output .= '<span class="album">'.$song["Album"].'</span>';
if ($song["Year"]){
$output .= '<span class="year">('.$song["Year"].')</span>';
}
$output .= '</div></div></li>';
}
// end the table
$output .= '</ul>';
// show my new table
print ($output);
}
?>
<script type="text/javascript">
<!--
$(document).ready(function(){
ls = "http://click.linksynergy.com/fs-bin/stat?id=xeQpzTLnJ8I&offerid=94348&type=3&subid=0&tmpid=2192&RD_PARM1="; // LinkShare URL
itunesAPI = "http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/wsSearch?term="; // iTunes API
itunesMP4 = new Array();
var url = new Array();
var artwork = new Array();
var album = new Array();
var itunesSong = new Array();
var itunesURL = new Array();
var lsURL = new Array();
var i=0;
$('#myitunes > .item').each(function(){ // iTunes XMLの要素数だけ繰り返す
// 曲テキスト情報を抽出
var song = $(this).find('.song').text();
var artist = $(this).find('.artist').text();
var album = $(this).find('.album').text();
var keyword = song + '+' + artist + '+' + album;
// 検索用に文字列を置換(スペース、記号など)
keyword = keyword.replace(/ \u0026 /g, "+");
keyword = keyword.replace(/\u002f/g, "+");
keyword = keyword.replace(/\u0023/g, "");
keyword = keyword.replace(/ /g, "+");
url[i] = itunesAPI+keyword+"&country=jp&media=music&entity=musicTrack&callback=?";
itunesLoad(url[i],i,song,artist,$(this));
i++;
});
function itunesLoad(url,n,song,artist,thisis) {
$.getJSON(url,function(data){
if (data.results[0]){ // iTunesから情報が返ってきた曲のみ処理する
itunesSong[n] = data.results[0].trackName;
album[n] = data.results[0].collectionName;
artwork[n] = data.results[0].artworkUrl30;
itunesURL[n] = data.results[0].trackViewUrl;
itunesMP4[n] = data.results[0].previewUrl;
lsURL[n] = ls + itunesURL[n];
$(thisis).find('.artwork').html('<i class="itsPlay" /><img src="' + artwork[n] + '" width="30" height="30" alt="' + album[n] + '" />');
$(thisis).find('.song').html('<a href="' + lsURL[n] + '" target="_blank" onClick="recordOutboundLink(this, \'OutboundLink-iTS\', \'' + song + ' - ' + artist + '\');return false;">' + song + '</a>');
$(thisis).css("display","block");
} else { // iTunesから情報が返ってこなかったら非表示とする
}
});
}
});
//-->
</script>
</div>
view raw gistfile1.html hosted with ❤ by GitHub
Googleさんは、この記事をこう解釈しました

記事の詳細ページ

記事の全文を表示します。関連するコメントやトラックバックなどもこちらからどうぞ。

本日のBGM

★印は「これは聴いてみてほしい!」という推薦曲です。曲名をクリックするとiTunes Storeへジャンプします。アートワークをクリックすると、この場で再生できます。

'; // loop through the songs in the array and get 4 fields that I want to see foreach ($songs as $song) { $output .= '
  • '; if ($song["Rating"] == 100){ $output .= ''.$song["Rating"].''; } $output .= '
    '; $output .= '
    '.$song["Name"].''; $output .= '
    '.$song["Artist"].''; $output .= ''.$song["Album"].''; if ($song["Year"]){ $output .= '('.$song["Year"].')'; } $output .= '
  • '; } // end the table $output .= ''; // show my new table print ($output); } ?>

    Now & Then

    Twitter Updates

      OAuthRequest('https://api.twitter.com/1.1/statuses/user_timeline.json','GET',array('screen_name' =>$search_word,'count' =>'3')); //Jsonデータをオブジェクトに変更 $oObj = json_decode($vRequest); //var_dump(json_decode($vRequest)); //オブジェクトを展開 for($i_tweet = 0; $i_tweet < sizeof($oObj); $i_tweet++){ $screen_name = $oObj[$i_tweet] -> {'screen_name'};//ユーザーID $profile_image_url = $oObj[$i_tweet] -> {'profile_image_url'};//プロフィール画像のURL $text = $oObj[$i_tweet] -> {'text'};//ツイート $date = $oObj[$i_tweet] -> {'created_at'};//時間 $tweet_time=strtotime($date);//Unixタイムスタンプ形式に変換 $now_time=time();//現在の時刻をUnixタイムスタンプで取得 $relative_time=$now_time-$tweet_time;//つぶやかれたのが何秒前か if($relative_time<60){//ss $displayTime = $relative_time.'秒前'; }elseif($relative_time>=60 && $relative_time<(60*60)){//mm $displayTime = floor($relative_time/60).'分前'; }elseif($relative_time>=(60*60) && $relative_time<(60*60*24)){//hh $displayTime = floor($relative_time/(60*60)).'時間前'; }elseif($relative_time>=(60*60*24)){//日付 $displayTime = date('n月j日',$tweet_time); } //表示 echo '
    • ' . $text .'' . $displayTime . '
    • '; } ?>
    follow me on Twitter