|
【ブラウザはGoogle Chrome】
●最新版ダウンロードはこちら 【お知らせ】Windows7でChromeがフリーズを起こす場合は、コントロールパネル⇒管理ツール⇒サービス でWindows Media Player Network Sharing Serviceを停止かつ無効にします。Micorosoftのバグです。 |
【YouTube API】【JavaScriptでYouTube APIを使う方法】【ソース公開】 |
|
【リンクフリー】 私設研究所ネオテックラボ Neo-Tech-Lab.co.uk 【記載者】 私設研究所Neo-Tech-Lab.com 上田智章 【掲載日】2011年05月17日 |
|
ここにチェックボックス型外部コンテンツ・メニューが入ります。 | |
|
【ブラウザはGoogle Chrome】
●最新版ダウンロードはこちら 【お知らせ】Windows7でChromeがフリーズを起こす場合は、コントロールパネル⇒管理ツール⇒サービス でWindows Media Player Network Sharing Serviceを停止かつ無効にします。Micorosoftのバグです。 |
【はじめに】YouTubeには、VocaloidやMikuMikuDance関連の動画がとても豊富なので、自サイトのBGMとしてかなり以前より利用させてもらっている。でも、YouTube標準の埋め込み型プレーヤー(Embedded Player)は1曲だけしか演奏できずとても不便だ。 YouTubeには再生リストを自分で作って再生させる方法もあるが、コントロールに制約があり、画面にテロップも流せない。 更にYouTubeにありがちな事なのだが、選択していた動画が様々な理由で突然削除されてしまう事もある。 そこで、いろいろ試行錯誤して再生リストを管理するBGM Playerをこれまで何回も作り直してきた。 何回も作り直すのは好きでやっているのではなくて、YouTubeがたびたび仕様変更を実施して大きなバグを発生するからだ。 サイト側で動画情報と削除の有無を巡回管理するBGM player Version1.00を製作したのだが、 YouTube側のページアクセス方法が突然規制されてしまい、巡回ソフト(Web Agent)の負荷増大等のいろいろな問題が発生してしまった。 概ね半年に1回はこういう迷惑なバージョン改定が発生するので、その度に作り直しを余儀なくされてきた。 現状は初期の頃の作りとかなり差が生じてしまったので、今回記事を書きなおすことにした。 基本的にJavaは一切使わず、JavaScriptだけで記述している。(最新版でさえJavaScriptのみです。) 実際、悪意のソフトウェアではJavaが使われることが多いので、 もしパソコンであればJavaのアンインストールをお薦めする。 /2013/02/07/ 【追記】 初期の頃には、ディベロッパー登録を行ってキーを取得し、SWFobjectを使う方法を採用していたが、現状は使っていない。 SWFobjectは再生タイマーの呼び出し、ボリューム調整など行えるのだが、残念な事にバグが多すぎる欠点がある。 最悪なのは、スクリーン上から動画表示領域が外れた状態で、再生が停止してしまう不具合。 最後まで再生が完了せず、最後の少し手前でフリーズするバグ。 数えればきりがない。ブラウザごとに応答が違い過ぎるので、これも問題だ。 結局、GDataで動画の再生時間を調べ、外部タイマーで時間管理を行う方法が手堅い。 そんなこんなで、普通の埋め込みにautoplayとwmodeのパラメータを追加するだけで使っている。 |
【サンプル9】≪動画IDと表示属性の再生リストを持ち、自動削除対応版のBGMプレーヤー≫多機能挑戦中のBGM Player Ⅲβ版仕様です。再生停止時、ChromeとFireFoxでWebGLを表示させる実験中です。 実は2011年07月時点で、base64形式のbmpファイルをデータコンテナにした3次元ポリゴンモデルデータ (PMD)をクロスドメインでダウンロードする技術は開発済みなのですが、まだ複雑なポリゴンモデルを 表示させることはできていません。どうしても読込時間が長くなってしまいますね。 MMDをインターネット上に持ち込むにはHTML5の浸透を待つ必要があるようです。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample9.htm |
【サンプル8】≪動画IDと表示属性の再生リストを持ち、自動削除対応版のBGMプレーヤー≫swfObjectを使って削除動画を検出している最新版のサンプルです。基本的に再生リストには動画IDをJSON形式で登録するだけです。 サンプルでは動画所有者情報も記録しています。 再生リストに削除された動画IDも2013年2月現在12件混入させています。 並列的に別タスクで削除動画を探索しているようすがわかるようにしています。 概ね40秒程度で削除動画を自動検出して、自分で削除します。 現在のBGM Player IIに比較的近い仕様です。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample8.htm |
【サンプル6】≪動画IDのみの再生リストを持ち、ランダム再生、自動削除対応版のプレーヤー≫swfObjectを使っている最新版のサンプルです。swfObjectは動画の記録時間を調べて実在する動画か否か調べるのに使っているだけです。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample6.htm パラメータ無しの場合は、NTL_YTの初期設定に基づいて再生が始まります。 1つ目の動画は初期設定でIDを指定することができます。NTL_YTのJSONの id: "<動画ID>" を設定しておけばOKです。 また、パラメータで指定することもできます。 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample6.htm?w=480&h=320&id=nvcKv85FcYU 動画スクリーンのサイズをwとhのパラメータで指定し、動画IDをidで指定しています。 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample6.htm?w=320&h=240 動画スクリーンのサイズをwとhのパラメータで指定する場合です。 |
【サンプル1】≪画面サイズ(横幅画素数と縦高画素数)と動画IDをパラメータで指定する方法≫サンプル1は、画面サイズ(横幅画素数と縦高画素数)と動画IDを1曲だけパラメータで指定して自動再生を行う。YouTube_Sample1.htm?w=[横幅画素数]&h=[縦高画素数]&id=[動画ID] の形式で使う。 主要ブラウザGoogle Chrome, IE, Fire Fox, Opera, Apple Safariで動作する。 下記例では横幅585画素、縦高400画素の大きさの画面で動画ID(K7PPbDuHyrg)を自動再生する。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample1.htm?w=585&h=400&id=K7PPbDuHyrg |
【HTML】<body onload="NTL_YTGetParameter();"> <div id="YTPlayer" name="YTPlayer" style="position:relative;top:0px;left:0px;" bgcolor="black"></div> </body> 【JavaScriptソース】動画再生時にオプションでwmode=transparentと透過属性を指定しているが、これは動画スクリーンの上に文字やロゴを表示したい場合に使うオプションです。通常はこの指定を行う必要はありません。 このページに表示されているBGM Playerでは、スクリーン上に『Neo-Tech-Lab.com BGM Player II』と表示されています。 これは、divタグのstyleにあるzIndexを使って複数のレイヤーを構成し、手前にこのテキストが存在するからなのですが、 wmode=transparentと指定しないと、zIndexの指定だけでは手前に表示することはできないのです。 但し、wmode=transparentを指定するとFlash Playerの挙動がブラウザ毎に微妙に差異が出てくるので、コーディングには 配慮が必要となります。 //******************************************************************************* //【YouTube動画を動的に埋め込み再生する】 // Copyright by ☆Tomoaki Ueda☆ /2013/01/14/ Kyoto, Japan, 612-0056 //【ご利用方法】 // パラメータ w=[横幅画素数] h=[縦高画素数] id=[YouTube動画ID] // 例:YouTube_Sample1.htm?w=640&h=495&id=K7PPbDuHyrg // 例:http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample1.htm?w=585&h=400&id=K7PPbDuHyrg //******************************************************************************* function NTL_YTGetParameter() { var param = location.search.substring(1).split('&'); // location.searchで『?』以降のパラメータを取得する var arg = new Object(); for(var i = 0; param[i]; i++) { var elements = param[i].split('='); arg[elements[0]] = elements[1]; } if(arg["id"]==undefined) { arg["w"]="585px"; arg["h"]="400px"; arg["id"]="K7PPbDuHyrg"; } NTL_YTPlayer(arg["w"], arg["h"], arg["id"]); } //******************************************************************************* //【NTL_YTPlayer】 // ≪オプション≫ ループ再生:loop=1 自動再生:autoplay=1 透過属性:wmode=transparent // ○Google Chrome, IE, Opera, FireFox, Safari //******************************************************************************* function NTL_YTPlayer(yt_width, yt_height, yt_id) { var obj = document.createElement("iframe"); obj.setAttribute("frameBorder","0"); obj.width = yt_width; obj.height = yt_height; obj.src = "http://www.youtube.com/embed/" + yt_id + "?autoplay=1&wmode=transparent"; document.getElementById("YTPlayer").appendChild(obj); } |
【サンプル2】≪GDataを使って動画情報をJSON(P)形式で取得する方法≫サンプル2は、画面サイズ(横幅画素数と縦高画素数)と動画IDを1曲だけパラメータで指定して自動再生を行う。YouTube_Sample1.htm?w=[横幅画素数]&h=[縦高画素数]&id=[動画ID] の形式で使う。 主要ブラウザGoogle Chrome, IE, Fire Fox, Opera, Apple Safariで動作する。 サンプル1との違いは、GDataを使って、動画IDに基づいてJSON(P)形式で動画情報を取得・表示する点です。 動画情報には、動画の再生時間(duration)も含まれているので、再生時間の管理もこの値を使って行います。 YouTubeはピーク負荷によっても異なるが再生開始までに1~3秒を要するので終了時間を動画再生時間(duration) より3秒間長くとっている。 下記例では横幅585画素、縦高400画素の大きさの画面で動画ID(K7PPbDuHyrg)を自動再生する。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample2.htm?w=585&h=400&id=yR80uWtEp2c |
【HTML】<body onload="NTL_YTGetParameter();"> <div id="YTPlayer" name="YTPlayer" style="position:relative;top:0px;left:0px;background-color:'black';"></div><br> <div id="YTInfo" name="YTInfo" style="background-color:'lightgray';"></div> </body> 【JavaScriptソース】//******************************************************************************* //【YouTube動画を動的に埋め込み再生する】 // Copyright by ☆Tomoaki Ueda☆ /2013/01/14/ Kyoto, Japan, 612-0056 //【ご利用方法】 // パラメータ w=[横幅画素数] h=[縦高画素数] id=[YouTube動画ID] // 例:YouTube_Sample2.htm?w=640&h=495&id=K7PPbDuHyrg // 例:http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample2.htm?w=585&h=400&id=yR80uWtEp2c //******************************************************************************* var NTL_YTInfo; var NTL_YTTimer; function NTL_YTGetParameter() { var param = location.search.substring(1).split('&'); // location.searchで『?』以降のパラメータを取得する var arg = new Object(); for(var i = 0; param[i]; i++) { var elements = param[i].split('='); arg[elements[0]] = elements[1]; } NTL_YTInfo = { "width": arg["w"], //【横幅画素数】 "height": arg["h"], //【縦高画素数】 "id": arg["id"], //【動画ID】半角英数11桁 "AuthorName": "", //【作者】 "Published": "", //【アップロード日付】 "Title": "", //【題名】 "ViewCount": 0, //【再生回数】 "FavoriteCount": 0, //【お気に入り登録】 "Duration": 0 //【初期化】 }; NTL_RequestYTInfo(NTL_YTInfo.id); //【JSON要求】⇒【JSON取得】⇒【再生】 NTL_YTTimer = setTimeout("NTL_ShowErrorVideo()", 10000); //【10秒間無応答ならエラー発生】 } function NTL_ShowErrorVideo() { clearTimeout(NTL_YTTimer); NTL_RequestYTInfo("sPB9-dkzuC4"); //【JSON要求】⇒【JSON取得】⇒【削除メッセージ動画再生】 } //******************************************************************************* //【NTL_YTPlayer】 // ≪オプション≫ ループ再生:loop=1 自動再生:autoplay=1 透過属性:wmode=transparent // ○Google Chrome, IE, Opera, FireFox, Safari //******************************************************************************* function NTL_YTPlayer(yt_width, yt_height, yt_id) { var obj = document.createElement("iframe"); obj.setAttribute("frameBorder","0"); obj.width = yt_width; obj.height = yt_height; obj.src = "http://www.youtube.com/embed/" + yt_id + "?autoplay=1&wmode=transparent"; document.getElementById("YTPlayer").appendChild(obj); } //******************************************************************************* //【NTL_RequestYTInfo】GDataのJSON形式動画情報を要求する //******************************************************************************* function NTL_RequestYTInfo(yt_id) { var STag = document.createElement("script"); //【scriptタグ要素を用意してJSONを要求するURLをsrcとする】 STag.charset = "utf-8"; // エンコードをutf-8とし、型をテキスト/JavaScriptとする STag.type = "text/javascript"; // JSONデータ受取の為のfunction[GetYouTubeMovieRecord]をcallbackで定義する STag.src = "http://gdata.youtube.com/feeds/api/videos?alt=json&q=" + yt_id + "&callback=NTL_GetYTInfo"; document.body.appendChild(STag); //【上記JSONデータを要求する要素をbodyにappendする】 } //******************************************************************************* //【NTL_GetYTInfo】 GDataのJSON形式動画情報を取得する //******************************************************************************* function NTL_GetYTInfo(Feed) { NTL_YTInfo.AuthorName = Feed.feed.entry[0].author[0].name.$t; //【動画所有者名】YouTubeチャンネルの名称 NTL_YTInfo.Published = Feed.feed.entry[0].published.$t; //【アップロード日時】 NTL_YTInfo.Title = Feed.feed.entry[0].title.$t; //【題名】 NTL_YTInfo.ViewCount = Feed.feed.entry[0].yt$statistics.viewCount; //【再生回数】 NTL_YTInfo.FavoriteCount = Feed.feed.entry[0].yt$statistics.favoriteCount; //【お気に入り登録】 NTL_YTInfo.Duration = Feed.feed.entry[0].media$group.yt$duration.seconds; //【動画再生時間】【秒】 NTL_YTInfo.Published = NTL_YTInfo.Published.replace(/-/g, "/"); NTL_YTInfo.Published = NTL_YTInfo.Published.replace(/T/, " "); clearTimeout(NTL_YTTimer); NTL_ShowYTInfo(); NTL_YTPlayer(NTL_YTInfo.width, NTL_YTInfo.height, NTL_YTInfo.id); NTL_YTTimer = setTimeout("NTL_ShowEndVideo()", (Number(NTL_YTInfo.Duration) + 3) * 1000); //【再生時間+3秒の余裕を与える】 } //***************************************************** //【動画情報の表示】 //***************************************************** function NTL_ShowYTInfo() { var rem = "【タイトル】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + NTL_YTInfo.id + "' target='_blank'>" + NTL_YTInfo.Title +"</a><br>" + "【動画ID】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + NTL_YTInfo.id + "' target='_blank'>" + NTL_YTInfo.id + "</a>" + " 【記録時間】" + NTL_YTInfo.Duration + "【秒】<br>" + "【所有者】<a title='YouTubeの所有者のチャンネルに遷移します。' href='http://www.youtube.com/user/" + NTL_YTInfo.AuthorName + "' target='_blank'>" + NTL_YTInfo.AuthorName +"</a><br>" + "【アップロード日時】" + NTL_YTInfo.Published.substring(0,16) +"<br>" + "【再生回数】" + NTL_YTInfo.ViewCount + " 【お気に入り登録】" + NTL_YTInfo.FavoriteCount + "<br>"; document.getElementById('YTInfo').innerHTML = rem; } //***************************************************** //【動画情報の表示】 //***************************************************** function NTL_ShowEndVideo() { clearTimeout(NTL_YTTimer); document.getElementById('YTInfo').innerHTML += "<br>再生が終了しました。"; } |
【Data APIの使い方】Google Data API(GData)にはいろいろな形式があるが、JavaScriptでクロスドメインでデータを受け取るのに適したJSON形式を用いた。まず、ブラウザのアドレス欄に『http://gdata.youtube.com/feeds/api/videos?alt=json&q=【動画ID】』と打ち込んでみてほしい。 【動画ID】とは、各動画ページのURL(例:http://www.youtube.com/watch?v=RvDLOeK5HRc&feature=feedrec_grec_index)の『watch?v=』の後に付いている11桁の半角英数字の事だ。 試しに、『http://gdata.youtube.com/feeds/api/videos?alt=json&q=RvDLOeK5HRc』と打ち込んでみる。 すると、テキストで {"version":"1.0","encoding":"UTF-8","feed":{"xmlns":"http://www.w3.org/2005/Atom","xmlns$media":"http://search.yahoo.com/mrss/","xmlns$openSearch":"http://a9.com/-/spec/opensearchrss/1.0/","xmlns$gd":"http://schemas.google.com/g/2005","xmlns$yt":"http://gdata.youtube.com/schemas/2007","id":{"$t":"http://gdata.youtube.com/feeds/api/videos"},"updated":{"$t":"2011-05-18T05:29:35.586Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://gdata.youtube.com/schemas/2007#video"}],"title":{"$t":"YouTube Videos matching query: RvDLOeK5HRc","type":"text"},"logo":{"$t":"http://www.youtube.com/img/pic_youtubelogo_123x63.gif"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.youtube.com"},{"rel":"http://schemas.google.com/g/2005#feed","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos"},{"rel":"http://schemas.google.com/g/2005#batch","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos/batch"},{"rel":"self","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos?alt\u003djson&q\u003dRvDLOeK5HRc&start-index\u003d1&max-results\u003d25"}],"author":[{"name":{"$t":"YouTube"},"uri":{"$t":"http://www.youtube.com/"}}],"generator":{"$t":"YouTube data API","version":"2.0","uri":"http://gdata.youtube.com/"},"openSearch$totalResults":{"$t":1},"openSearch$startIndex":{"$t":1},"openSearch$itemsPerPage":{"$t":25},"entry":[{"id":{"$t":"http://gdata.youtube.com/feeds/api/videos/RvDLOeK5HRc"},"published":{"$t":"2010-09-01T16:37:13.000Z"},"updated":{"$t":"2011-03-28T12:41:30.000Z"},"category":[{"scheme":"http://schemas.google.com/g/2005#kind","term":"http://gdata.youtube.com/schemas/2007#video"},{"scheme":"http://gdata.youtube.com/schemas/2007/categories.cat","term":"Music","label":"Music"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"VOCALOID"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"ゆうゆP"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"マクー"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"はるよ"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"深海少女"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"ミクオリジナル曲"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"VOCALOID新曲リンク"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"初音ミク"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"VOCALOID-PV"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"うん、深いな"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"underwater diving"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"scuba"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"widescreen"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"synthesized singing"},{"scheme":"http://gdata.youtube.com/schemas/2007/keywords.cat","term":"anime music"}],"title":{"$t":"【初音ミク】 深海少女 【オリジナル】[HD1080p]","type":"text"},"content":{"$t":"【初音ミク】 深海少女 【オリジナル】 NICONICODOUGA 2010年09月01日 ゆうゆ さんwww.nicovideo.jp 【作者のコメント】 Music : ゆうゆ(user/325945) Vocal : 初音ミクIllust : はるよ(mylist/3540872) Bg&Movie : マクー(mylist/12715161) 深海少女、どこまで沈む? ▼カラオケ音源はこちらです ⇒tsubu.ath.cx ■この度、日本クラウン様からアルバム「四季彩の星」を出していただける事になりまんた ⇒yuu-yu.jp","type":"text"},"link":[{"rel":"alternate","type":"text/html","href":"http://www.youtube.com/watch?v\u003dRvDLOeK5HRc&feature\u003dyoutube_gdata"},{"rel":"http://gdata.youtube.com/schemas/2007#video.responses","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos/RvDLOeK5HRc/responses"},{"rel":"http://gdata.youtube.com/schemas/2007#video.related","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos/RvDLOeK5HRc/related"},{"rel":"http://gdata.youtube.com/schemas/2007#mobile","type":"text/html","href":"http://m.youtube.com/details?v\u003dRvDLOeK5HRc"},{"rel":"self","type":"application/atom+xml","href":"http://gdata.youtube.com/feeds/api/videos/RvDLOeK5HRc"}],"author":[{"name":{"$t":"Miraclemilktea3"},"uri":{"$t":"http://gdata.youtube.com/feeds/api/users/miraclemilktea3"}}],"gd$comments":{"gd$feedLink":{"href":"http://gdata.youtube.com/feeds/api/videos/RvDLOeK5HRc/comments","countHint":1}},"media$group":{"media$category":[{"$t":"Music","label":"Music","scheme":"http://gdata.youtube.com/schemas/2007/categories.cat"}],"media$content":[{"url":"http://www.youtube.com/v/RvDLOeK5HRc?f\u003dvideos&app\u003dyoutube_gdata","type":"application/x-shockwave-flash","medium":"video","isDefault":"true","expression":"full","duration":218,"yt$format":5},{"url":"rtsp://v4.cache4.c.youtube.com/CiILENy73wIaGQkXHbniOcvwRhMYDSANFEgGUgZ2aWRlb3MM/0/0/0/video.3gp","type":"video/3gpp","medium":"video","expression":"full","duration":218,"yt$format":1},{"url":"rtsp://v2.cache7.c.youtube.com/CiILENy73wIaGQkXHbniOcvwRhMYESARFEgGUgZ2aWRlb3MM/0/0/0/video.3gp","type":"video/3gpp","medium":"video","expression":"full","duration":218,"yt$format":6}],"media$description":{"$t":"【初音ミク】 深海少女 【オリジナル】 NICONICODOUGA 2010年09月01日 ゆうゆ さんwww.nicovideo.jp 【作者のコメント】 Music : ゆうゆ(user/325945) Vocal : 初音ミクIllust : はるよ(mylist/3540872) Bg&Movie : マクー(mylist/12715161) 深海少女、どこまで沈む? ▼カラオケ音源はこちらです ⇒tsubu.ath.cx ■この度、日本クラウン様からアルバム「四季彩の星」を出していただける事になりまんた ⇒yuu-yu.jp","type":"plain"},"media$keywords":{"$t":"VOCALOID, ゆうゆP, マクー, はるよ, 深海少女, ミクオリジナル曲, VOCALOID新曲リンク, 初音ミク, VOCALOID-PV, うん、深いな, underwater diving, scuba, widescreen, synthesized singing, anime music"},"media$player":[{"url":"http://www.youtube.com/watch?v\u003dRvDLOeK5HRc&feature\u003dyoutube_gdata_player"}],"media$thumbnail":[{"url":"http://i.ytimg.com/vi/RvDLOeK5HRc/0.jpg","height":240,"width":320,"time":"00:01:49"},{"url":"http://i.ytimg.com/vi/RvDLOeK5HRc/1.jpg","height":90,"width":120,"time":"00:00:54.500"},{"url":"http://i.ytimg.com/vi/RvDLOeK5HRc/2.jpg","height":90,"width":120,"time":"00:01:49"},{"url":"http://i.ytimg.com/vi/RvDLOeK5HRc/3.jpg","height":90,"width":120,"time":"00:02:43.500"}],"media$title":{"$t":"【初音ミク】 深海少女 【オリジナル】[HD1080p]","type":"plain"},"yt$duration":{"seconds":"218"}},"gd$rating":{"average":5.0,"max":5,"min":1,"numRaters":15,"rel":"http://schemas.google.com/g/2005#overall"},"yt$recorded":{"$t":"2010-09-02"},"yt$statistics":{"favoriteCount":"34","viewCount":"7128"}}]}} のように表示されたはずだ。これがJSONデータだ。 JavaScriptにはこのデータを構造体データとして受け取る仕組みが用意されていて、URLの後ろに『&callback=関数名』を付けておくと、データが返送されてきた時にその関数が呼ばれ、引数に構造体データとして値が引き渡される。下にコードサンプルを示す。使い方は簡単で、関数 RequestYouTubeMovieRecord('RvDLOeK5HRc'); を実行すれば、GetYouTubeMovieRecord(Feed)がcallbackされる。 サンプルでは引数FeedにJSONデータを代入している。どんなデータがあるのかは、Internet Explorer9に標準で装備されたF12 開発者ツール(L)を用いて、ブレークポイントを設定して、watch機能でFeedを登録して、階層構造を調べた。なので、Googleさんの仕様書は殆ど全く読んでおりませんのでご容赦ください。 【コードサンプル】//【Public変数の登録】 var YT_AuthorName; //【動画所有者名】 = Feed.feed.entry[0].author[0].name.$t; var YT_Published; //【アップロード日時】= Feed.feed.entry[0].published.$t; var YT_Title; //【題名】 = Feed.feed.entry[0].title.$t; var YT_ViewCount; //【再生回数】 = Feed.feed.entry[0].yt$statistics.viewCount; //******************************************************* //【Get YouTube Movie Record】【callback】 //******************************************************* function RequestYouTubeMovieRecord(id) { YT_AuthorName = ""; //【要求するデータの全項目をクリアする】 YT_Published = ""; // YT_Title = ""; // YT_ViewCount = 0; // var STag = document.createElement("script"); //【scriptタグ要素を用意してJSONを要求するURLをsrcとする】 STag.charset = "utf-8"; // エンコードをutf-8とし、型をテキスト/JavaScriptとする STag.type = "text/javascript"; // JSONデータ受取の為のfunction[GetYouTubeMovieRecord]をcallbackで定義する STag.src = "http://gdata.youtube.com/feeds/api/videos?alt=json&q=" + id + "&callback=GetYouTubeMovieRecord"; document.body.appendChild(STag); //【上記JSONデータを要求する要素をbodyにappendする】 } function GetYouTubeMovieRecord(Feed) { //【Googleから返送されたJSONデータを構造体データとして引き数Feedで受け取る】 YT_AuthorName = Feed.feed.entry[0].author[0].name.$t; //【動画所有者名】YouTubeチャンネルの名称 YT_Published = Feed.feed.entry[0].published.$t; //【アップロード日時】 YT_Title = Feed.feed.entry[0].title.$t; //【題名】 YT_ViewCount = Feed.feed.entry[0].yt$statistics.viewCount; //【再生回数】(他にお気に入り登録や動画説明等のデータもある。) } |
【サンプル3】≪再生リストの中からランダムに再生を行う方法≫サンプル3は、指定画面サイズ(横幅画素数と縦高画素数)で再生リストの動画をランダムに選択して自動再生を行う。再生リスト(NTL_MusicList)は動画IDだけを記録した配列です。JavaScriptでは登録個数はNTL_MusicList.lengthで得られます。 YouTube_Sample1.htm?w=[横幅画素数]&h=[縦高画素数](&id=[動画ID]) の形式で使う。但し、動画IDは省略することができる。 主要ブラウザGoogle Chrome, IE, Fire Fox, Opera, Apple Safariで動作する。 下記例で、動画IDを指定した場合は最初にその動画を再生した後で、MusicListに基づいてランダム再生を行う。 動画IDを指定せずに省略した場合はMusicListに基づくランダム再生のみを行う。 各動画の再生時間はGDataのJSON(P)形式の動画情報のDurationで管理される。 【使い方】 http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample3.htm?w=585&h=400&id=K7PPbDuHyrg http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample3.htm?w=585&h=400 |
【HTML】<body onload="NTL_YTGetParameter();"> <div id="YTPlayer" name="YTPlayer" style="position:relative;top:0px;left:0px;background-color:'black';"></div><br> <div id="YTInfo" name="YTInfo" style="background-color:'lightgray';"></div> </body> 【JavaScriptソース】//******************************************************************************* //【YouTube動画を動的に埋め込み再生する】 // Copyright by ☆Tomoaki Ueda☆ /2013/01/14/ Kyoto, Japan, 612-0056 //【ご利用方法】 // パラメータ w=[横幅画素数] h=[縦高画素数] id=[YouTube動画ID] // 例:YouTube_Sample2.htm?w=640&h=495&id=K7PPbDuHyrg // 例:http://www.neo-tech-lab.co.uk/YouTube/YouTube_Sample2.htm?w=585&h=400&id=yR80uWtEp2c //******************************************************************************* var NTL_MovieList = [ //【再生曲リスト】 "RMtZ_G-OwUs", //★☆★メランコリック試作1 "qyoAlh38Or0", //★☆★【MMD】トリノコシティ【Appearacne Miku】 "ZpaUy4TnD_8", //★☆★【MMD】ままま式あぴミクさんでサイバーサンダーサイダー "I1womLtDYb8", //★☆★【MMD】Weekender Girl //【Crypton】 "rqg4Eun7fgs", //【初音ミク】「ミクの日大感謝祭」ダイジェスト映像 "y2oTcAtAsNc", //[ミクの日感謝祭 39's Giving Day] 恋スルVOC@LOID (feat. 初音ミク) / OSTER Project "zBNWup41idY", //[ミクの日感謝祭 39's Giving Day] StargazeR (feat. 初音ミク) / 骨盤P "MO-7YxoE-pc", //[ミクの日感謝祭 39's Giving Day] 裏表ラバーズ (feat. 初音ミク) / wowaka "gucD0aURXv0", //[ミクの日感謝祭 39's Giving Day] 愛言葉 (feat. 初音ミク) / DECO*27 "Nn2aIYJqGPg", //【第8回MMD杯本選】 天ノ弱 【MMD-PV】 [HD1080p] //【LAT式】 "MfnFKZ5nBQU", //MMD Packaged Lat Model Miku "aKv7sp4NhsU", //[MMD] 初音ミク 千本桜 "CleQxLRpV-I" //[MMD] Miki Miki ★ Romantic Night [MMD CUP IV] ]; var NTL_YTInfo; var NTL_YTTimer; function NTL_YTGetParameter() { var param = location.search.substring(1).split('&'); // location.searchで『?』以降のパラメータを取得する var arg = new Object(); for(var i = 0; param[i]; i++) { var elements = param[i].split('='); arg[elements[0]] = elements[1]; } NTL_YTInfo = { "count": 0, //【動画再生回数】 "width": arg["w"], //【横幅画素数】 "height": arg["h"], //【縦高画素数】 "id": arg["id"], //【動画ID】半角英数11桁 "AuthorName": "", //【作者】 "Published": "", //【アップロード日付】 "Title": "", //【題名】 "ViewCount": 0, //【再生回数】 "FavoriteCount": 0, //【お気に入り登録】 "Duration": 0 //【動画再生時間】 }; if(NTL_YTInfo.id==undefined) { NTL_YTInfo.id = NTL_SelectId(); } NTL_SetNextVideo(); } function NTL_ShowErrorVideo() { clearTimeout(NTL_YTTimer); NTL_RequestYTInfo("sPB9-dkzuC4"); //【JSON要求】⇒【JSON取得】⇒【削除メッセージ動画再生】 } //******************************************************************************* //【NTL_YTPlayer】 // ≪オプション≫ ループ再生:loop=1 自動再生:autoplay=1 透過属性:wmode=transparent // ○Google Chrome, IE, Opera, FireFox, Safari //******************************************************************************* function NTL_YTPlayer(yt_width, yt_height, yt_id) { document.getElementById("YTPlayer").innerHTML = ""; var obj = document.createElement("iframe"); obj.setAttribute("frameBorder","0"); obj.width = yt_width; obj.height = yt_height; obj.src = "http://www.youtube.com/embed/" + yt_id + "?autoplay=1&wmode=transparent"; document.getElementById("YTPlayer").appendChild(obj); } //******************************************************************************* //【NTL_RequestYTInfo】GDataのJSON形式動画情報を要求する //******************************************************************************* function NTL_RequestYTInfo(yt_id) { var STag = document.createElement("script"); //【scriptタグ要素を用意してJSONを要求するURLをsrcとする】 STag.charset = "utf-8"; // エンコードをutf-8とし、型をテキスト/JavaScriptとする STag.type = "text/javascript"; // JSONデータ受取の為のfunction[GetYouTubeMovieRecord]をcallbackで定義する STag.src = "http://gdata.youtube.com/feeds/api/videos?alt=json&q=" + yt_id + "&callback=NTL_GetYTInfo"; document.body.appendChild(STag); //【上記JSONデータを要求する要素をbodyにappendする】 } //******************************************************************************* //【NTL_GetYTInfo】 GDataのJSON形式動画情報を取得する //******************************************************************************* function NTL_GetYTInfo(Feed) { NTL_YTInfo.AuthorName = Feed.feed.entry[0].author[0].name.$t; //【動画所有者名】YouTubeチャンネルの名称 NTL_YTInfo.Published = Feed.feed.entry[0].published.$t; //【アップロード日時】 NTL_YTInfo.Title = Feed.feed.entry[0].title.$t; //【題名】 NTL_YTInfo.ViewCount = Feed.feed.entry[0].yt$statistics.viewCount; //【再生回数】 NTL_YTInfo.FavoriteCount = Feed.feed.entry[0].yt$statistics.favoriteCount; //【お気に入り登録】 NTL_YTInfo.Duration = Feed.feed.entry[0].media$group.yt$duration.seconds; //【動画再生時間】【秒】 NTL_YTInfo.Published = NTL_YTInfo.Published.replace(/-/g, "/"); NTL_YTInfo.Published = NTL_YTInfo.Published.replace(/T/, " "); clearTimeout(NTL_YTTimer); NTL_ShowYTInfo(); NTL_YTPlayer(NTL_YTInfo.width, NTL_YTInfo.height, NTL_YTInfo.id); NTL_YTTimer = setTimeout("NTL_SetNextVideo()", (Number(NTL_YTInfo.Duration) + 3) * 1000); //【再生時間+3秒の余裕を与える】 } //***************************************************** //【動画情報の表示】 //***************************************************** function NTL_ShowYTInfo() { var rem = "【タイトル】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + NTL_YTInfo.id + "' target='_blank'>" + NTL_YTInfo.Title +"</a><br>"; rem += "【動画ID】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + NTL_YTInfo.id + "' target='_blank'>" + NTL_YTInfo.id + "</a>"; rem += " 【記録時間】" + NTL_YTInfo.Duration + "【秒】<br>"; rem += "【所有者】<a title='YouTubeの所有者のチャンネルに遷移します。' href='http://www.youtube.com/user/" + NTL_YTInfo.AuthorName + "' target='_blank'>" + NTL_YTInfo.AuthorName +"</a><br>"; rem += "【アップロード日時】" + NTL_YTInfo.Published.substring(0,16) +"<br>"; rem += "【再生回数】" + NTL_YTInfo.ViewCount + " 【お気に入り登録】" + NTL_YTInfo.FavoriteCount + "<br>"; document.getElementById('YTInfo').innerHTML = rem; } //***************************************************** //【動画情報の表示】 //***************************************************** function NTL_SetNextVideo() { clearTimeout(NTL_YTTimer); if(NTL_YTInfo.count>0) { var i = NTL_SelectId(); while(NTL_YTInfo.id==i) { i = NTL_SelectId(); } NTL_YTInfo.id = i; } NTL_YTInfo.count++; NTL_RequestYTInfo(NTL_YTInfo.id); //【JSON要求】⇒【JSON取得】⇒【再生】 NTL_YTTimer = setTimeout("NTL_ShowErrorVideo()", 10000); //【10秒間無応答ならエラー発生】 } //***************************************************** //【動画の選曲】 //***************************************************** function NTL_SelectId() { return NTL_MovieList[Math.floor( Math.random() * (NTL_MovieList.length - 1))]; } |
【サンプル4】≪再生リストの動画が削除されていないかチェックする方法≫YouTubeでは、動画保有者の都合や著作権違反、あるいはサーバーデータ消失などの理由で、埋め込み非許可や非公開、あるいは削除されるケースが多いです。以前は、Agentプログラムに動画ページを巡回させたりしてチェックしていたが、段々とYouTubeサイドのガードが固くなり、あるいは頻繁な仕様変更によって、完全自動ではチェックすることができなくなってきました。ブランドページではGoogle Data APIで読み取れないようなケースも多発しています。これはAPIのバグなのか仕様なのかはわかりません。 サンプル4は、動画IDのリスト(NTL_PlayList配列)だけでGoogle Data APIを使ってステータスを調べることができます。 ただし、Google Data APIのみでは、非公開、限定公開、埋め込み非許可、削除の判断が微妙なので、この場合は、埋め込みを実際にページ内で行うようにしています。 が実際に削除されている場合の動画サムネールです。この場合は埋め込み動画も画面が暗くなり、再生することができないことがわかります。 【サンプル5】【NTL_BGMList.htm】漸く削除された可能性のある動画を絞り込めるところまで来たので、SWFobjectをもう一度採用してみることにしました。限定公開やYouTubeの不具合で、Google Dataが読めなくてもまだ生きている動画があることは確認できたので、SWFobjectのPlayerを起動して動画を読込、Duration(記録時間)を調べ、0なら削除されていると判断できることがわかりました。ただし、SWFobjectには少し不具合があり、正常な動画でも停止状態ではDurationが0になってしまう場合があります。そこでDurationが0の場合には強制的に再生を開始してDurationを読込み、無事読込めた場合には再生を停止させるようにしました。こうして完成したのが『サンプル5』です。絞り込みが終了してから10秒程待つと、削除動画のIDを表示します。 NTL_BGMList.htmは、このサイトの動画リストのうち、動画ツアー19番のチェックを行うコードです。 300件を超えると流石に少し時間がかかります。 |
【サンプル4のソース】<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Language" content="ja" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title>このページで埋め込み利用しているYouTube動画のリスト</title> <script type="text/javascript" src="/script/MoviePlayList.js"></script> <script type="text/javascript"> var NTL_PlayList = [ "ZpaUy4TnD_8", //★☆★【MMD】ままま式あぴミクさんでサイバーサンダーサイダー "I1womLtDYb8", //★☆★【MMD】Weekender Girl "y2oTcAtAsNc", //★★★★[ミクの日感謝祭 39's Giving Day] 恋スルVOC@LOID (feat. 初音ミク) / OSTER Project "zBNWup41idY", //★★★★[ミクの日感謝祭 39's Giving Day] StargazeR (feat. 初音ミク) / 骨盤P "MO-7YxoE-pc", //★★★★[ミクの日感謝祭 39's Giving Day] 裏表ラバーズ (feat. 初音ミク) / wowaka "gucD0aURXv0", //★★★★[ミクの日感謝祭 39's Giving Day] 愛言葉 (feat. 初音ミク) / DECO*27 "PUr15HBFVWE", //★【IA】メテオ【オリジナルPV】 "HE1sJfLkVjk", //★【MMD】 galaxias! ~IA~ "R5oekmftgMc", //★【再】IAさん達にgalaxias!を踊ってもらいました。[HD1080p] "6V_N3vAnauQ", //【VOCALOID MMD】Gravity=Reality【IA Model】 "0JglNR2k36o", //【VOCALOID IA】 Little HERO!! 【オリジナル】 "RMtZ_G-OwUs", //★☆★メランコリック試作1 "qyoAlh38Or0", //★☆★【MMD】トリノコシティ【Appearacne Miku】 "ZpaUy4TnD_8", //★☆★【MMD】ままま式あぴミクさんでサイバーサンダーサイダー "I1womLtDYb8", //★☆★【MMD】Weekender Girl "2eRgs6XJ-6g", //★★★★★【MMD】多重未来のカルテット~QUARTET THEME~ Tda式ミク・アペンド【HD】 "6E77Z7aqJCE", //★★★★★【MMD】ポーカーフェイス Tda式ミク・アペンド改変モデル【HD】 "sl17g1LGKdI", //★★★★★キャットフード - 初音ミク "q9bs1sDjzjc", //★★★★★【Hatsune Miku】 ODDS & ENDS + Mp3 Link "rqg4Eun7fgs", //★★★★★【初音ミク】「ミクの日大感謝祭」ダイジェスト映像 "5QJvzf0EarE", //★★★★★【MMD】 もう一度WAVEFILEを踊りたい 【第1回我家のレア様杯】 [HD1080p] "mlo4GN7lffg" //☆☆☆☆☆【初音ミク】「金の聖夜霜雪に朽ちて」PV ディレクターズカット版 ]; var YTinfo; var NTL_Language = "ja"; //【表示言語】 // var NTL_Tour=18; // 負の値のときは上記プレイリストで表示する var NTL_Tour= -1; // 負の値のときは上記プレイリストで表示する var NTL_Count = 0; var NTL_Timer; //******************************************************* //【Initialize】 //******************************************************* function Proc() { var n = NTL_PlayList.length; if(NTL_Tour>=0) { n = playlist.tour[NTL_Tour].movie_data.length; NTL_PlayList = new Array(n); for(var i=0; i<n; i++) { NTL_PlayList[i] = playlist.tour[NTL_Tour].movie_data[i].movie_id; } } InitializeYouTubeInformation(); InitializeDivTags(); SendRequest(); } //******************************************************* //【SendRequest】 //******************************************************* function SendRequest() { clearTimeout(NTL_Timer); RequestYouTubeMovieRecord(NTL_PlayList[NTL_Count]); NTL_Count++; if(NTL_Count<NTL_PlayList.length) { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>只今、No." + NTL_Count.toString() + "のデータを要求中</font></H2>"; NTL_Timer = setTimeout( SendRequest, 50 ); } else { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>巡回結果の検証を行っています</font></H2>"; NTL_Timer = setTimeout( CheckResult, 3000 ); } } //******************************************************* //【Initialize Div Tags】 //******************************************************* function InitializeDivTags() { var rem = ""; for(var i=0; i<NTL_PlayList.length; i++) { rem += "<table width='1000px' border='1' cellpadding='0' cellspacing='0' style='border-collapse: collapse; border-width: 0'>" + "<tr><td width='1000px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Title" + i.toString() + "' name='Title" + i.toString() + "'></div>" + " </td>" + "</tr>" + "</table>" + "<table width='1000px' border='1' cellpadding='0' cellspacing='0' style='border-collapse: collapse; border-width: 0'>" + "<tr><td width='130px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Icon" + i.toString() + "' name='Icon" + i.toString() + "'></div>" + " </td>" + " <td width='870px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Info" + i.toString() + "' name='Infon" + i.toString() + "'></div>" + " </td>" + "</tr>" + "</table>"; } document.getElementById("BGMList").innerHTML += rem; for(var i=0; i<NTL_PlayList.length; i++) { document.getElementById('Title' + i.toString()).innerHTML = "No." + i.toString() + " 動画ID[ <a title='【YouTubeの動画ページ】' href='http://www.youtube.com/watch?v=" + NTL_PlayList[i] + "' target='_blank'>" + NTL_PlayList[i] + "</a> ]"; document.getElementById('Icon' + i.toString()).innerHTML = "<img border='0' src='/b/ZZZZZZZZZZZ.jpg' width='120px' height='90px' />"; document.getElementById('Info' + i.toString()).innerHTML = "<font face='Times New Roman' size='4' color='red'><b>この動画は限定公開または非公開の動画であるか、<br>あるいは削除されている可能性があります。</b></font>"; } } //%%% Google YouTube Data API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //******************************************************* //【Initialize YouTube Information】 //******************************************************* function InitializeYouTubeInformation() { YTinfo = new Array(NTL_PlayList.length); var Obj = new Object(); for(var i=0; i<YTinfo.length; i++) { YTinfo[i] = { "id": NTL_PlayList[i], "AuthorName": "", "Published": "", "Title": "", "Thumbnail": Obj, "ViewCount": 0, "FavoriteCount": 0, "Duration": 0 }; } } //******************************************************* //【Request YouTube Movie Record】callback ==> GetYouTubeMovieRecord //******************************************************* function RequestYouTubeMovieRecord(id) { //【GData_JSON_Request】指定動画IDの動画情報をJSONデータ形式で要求する var STag = document.createElement("script"); //【scriptタグ要素を用意してJSONを要求するURLをsrcとする】 STag.charset = "utf-8"; // エンコードをutf-8とし、型をテキスト/JavaScriptとする STag.type = "text/javascript"; // JSONデータ受取の為のfunction[GetYouTubeMovieRecord]をcallbackで定義する STag.src = "http://gdata.youtube.com/feeds/api/videos?alt=json&q=" + id + "&callback=GetYouTubeMovieRecord"; document.body.appendChild(STag); //【上記JSONデータを要求する要素をbodyにappendする】 } //******************************************************* //【Get YouTube Movie Record】【callback】 //******************************************************* //指定動画IDの動画情報をJSONデータ形式で受け取る function GetYouTubeMovieRecord(Feed) { //【Googleから返送されたJSONデータを構造体データとして引き数Feedで受け取る】 if(Feed.feed.entry[0]==undefined) return; var Thumbnail = { url:"", height:0, width:0 }; Thumbnail.url = Feed.feed.entry[0].media$group.media$thumbnail[0].url; //【】url Thumbnail.height = Feed.feed.entry[0].media$group.media$thumbnail[0].height; //【】height Thumbnail.width = Feed.feed.entry[0].media$group.media$thumbnail[0].width; //【】width var s = Thumbnail.url.split("/"); var id = s[4]; for(var i=0; i<YTinfo.length; i++) { if(id==YTinfo[i].id) { YTinfo[i].AuthorName = Feed.feed.entry[0].author[0].name.$t; //【動画所有者名】YouTubeチャンネルの名称 YTinfo[i].Title = Feed.feed.entry[0].title.$t; //【題名】 YTinfo[i].ViewCount = Feed.feed.entry[0].yt$statistics.viewCount; //【再生回数】 (他に評価や動画説明等のデータもある。) YTinfo[i].FavoriteCount = Feed.feed.entry[0].yt$statistics.favoriteCount; //【評価】 YTinfo[i].Duration = Feed.feed.entry[0].media$group.yt$duration.seconds; //【動画再生時間】【秒】 YTinfo[i].Published = Feed.feed.entry[0].published.$t; //【アップロード日時】 YTinfo[i].Published = YTinfo[i].Published.replace(/-/g, "/"); // YTinfo[i].Published = YTinfo[i].Published.replace(/T/, " "); // YTinfo[i].Thumbnail = Thumbnail; // url, height, width, time //【表示内容更新】 var element1 = "Icon" + i.toString(); var element2 = "Info" + i.toString(); //***************************************************** //【サムネール表示】 //***************************************************** document.getElementById(element1).innerHTML = "<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + "<img border='0' src='" + YTinfo[i].Thumbnail.url + "' width='120px' height='90px' /></a>"; //***************************************************** //【動画情報の表示】 //***************************************************** var rem = ""; if (NTL_Language == 'ja') { rem += "【タイトル】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].Title +"</a><br>"; rem += "【所有者】<a title='YouTubeの所有者のチャンネルに遷移します。' href='http://www.youtube.com/user/" + YTinfo[i].AuthorName + "' target='_blank'>" + YTinfo[i].AuthorName +"</a> "; rem += "【動画ID】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].id + "</a> "; rem += "【記録時間】" + YTinfo[i].Duration + "【秒】<br>"; rem += "【アップロード日時】" + YTinfo[i].Published.substring(0,16) + " "; rem += "【再生回数】" + YTinfo[i].ViewCount + " "; rem += "【お気に入り登録】" + YTinfo[i].FavoriteCount + "<br>"; } else { // 'en': 英語表示モード rem += "【Title】<a title='Jump to Movie Page in YouTube' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].Title +"</a><br>"; rem += "【YouTube_Movie_ID】<a title='Jump to Movie Page in YouTube' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].id + "</a><br>"; rem += "【Owner】<a title='Jump to Owner_Channel in YouTube' href='http://www.youtube.com/user/" + YTinfo[i].AuthorName + "' target='_blank'>" + YTinfo[i].AuthorName +"</a><br>"; rem += "【Published Date】" + YTinfo[i].Published.substring(0,16) +"<br>"; rem += "【View Count】" + YTinfo[i].ViewCount + " 【Favorite Count】" + YTinfo[i].FavoriteCount + "<br>"; } document.getElementById(element2).innerHTML = rem; break; } } } //******************************************************* //【CheckResult】 //******************************************************* function CheckResult() { clearTimeout(NTL_Timer); var element1, element2; var Obj; var count=0; for(var i=0; i<NTL_PlayList.length; i++) { if((YTinfo[i].Title=="")&&(YTinfo[i].AuthorName=="")&&(YTinfo[i].Published=="")) { element1 = "Icon" + i.toString(); element2 = "Info" + i.toString(); document.getElementById(element1).innerHTML = "<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + "<img border='0' src='http://i1.ytimg.com/vi/" + YTinfo[i].id + "/default.jpg' width='120px' height='90px' /></a><br><br>"; NTL_YTPlayer(element2, 585, 370, YTinfo[i].id); count++; } } if(count!=0) { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>削除された可能性のある動画が" + count.toString() + "件見つかりました</font></H2>"; } else { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>削除された動画はありませんでした</font></H2>"; } } //******************************************************************************* //【NTL_YTPlayer】 // ≪オプション≫ ループ再生:loop=1 自動再生:autoplay=1 透過属性:wmode=transparent // ○Google Chrome, IE, Opera, FireFox, Safari //******************************************************************************* function NTL_YTPlayer(element, yt_width, yt_height, yt_id) { var obj = document.createElement("iframe"); obj.setAttribute("frameBorder","0"); obj.width = yt_width; obj.height = yt_height; obj.src = "http://www.youtube.com/embed/" + yt_id; // + "?autoplay=1&wmode=transparent"; document.getElementById(element).appendChild(obj); } window.onload = function () { Proc(); } </script> </head> <body background="/b/Background2.jpg"> <font face="Times New Roman" size="3"> <img src="/b/face1.png" width="100px"> <font color="pink">powered by</font> <a title="私設研究所Neo-Tech-Lab" href="http://www.neo-tech-lab.co.uk/"><font face="Times New Roman"><b><i><font color="black" size="5"><font color="red">Neo</font>-<font color="green">Tech</font>-<font color="blue">Lab</font>.<font color="brown">com</font></font></i></b></font></a><br> <font color="yellow" size="4"> ●このページで埋め込み利用しているYouTubeの動画のリストです。<br> ●当サイト自体には動画配信能力はなく、今表示中の動画は全てYouTubeから直接配信されています。<br> ●著作権はそれぞれの動画をYouTubeにアップロードした人に帰属しています。<br> 特にPerfumeをはじめとする実写動画は<a title="『Perfume』チャンネル" href="http://www.youtube.com/user/Perfume" target="_blank"><font color="white">『Perfume』公式チャンネル</font></a>(http://www.youtube.com/user/Perfume)と<br> <a title="『徳間ジャパン』さんのチャンネル" href="http://www.youtube.com/user/tokumajapan" target="_blank"><font color="white">『徳間ジャパン』さんのチャンネル</font></a>(http://www.youtube.com/user/tokumajapan)にアップロードされているものを利用しています。<br> ●当サイトのウェブ・エージェント'ミク'が、YouTubeの動画ページを1日に2回巡回して再生リストを管理しています。<br> ミクは参照元の動画が削除された事を検出すると自動的に再生リストからその動画IDを削除します。<br> ●最初の10曲は動画ツアー19番から実行されます。以降は動画ツアー18番に変更されます。<br> ●'ミク'のYouTube動画ページ巡回は、リンク繋がりによる『新曲探索』の目的も兼ねています。<br> あとは'ミク'にどうやって曲を評価させるか試行錯誤中なのですが、これはなかなかむずかしい問題ですね。<br> </font> <div id="ExecInfo" name="ExecInfo"><H2><font face='Times New Roman' color='red'>只今、YouTubeにデータの要求を開始します。</font></H2></div><br> <div id="BGMList" name="BGMList" style="width:1024px"> </div> </font> </body> </html> 【サンプル5のソース】<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja"> <head> <meta http-equiv="Content-Language" content="ja" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Script-Type" content="text/javascript" /> <meta http-equiv="Content-Style-Type" content="text/css" /> <title>このページで埋め込み利用しているYouTube動画のリスト</title> <script type="text/javascript" src="/script/MoviePlayList.js"></script> <script type="text/javascript" src="/script/swfobject.js"></script> <script type="text/javascript"> var NTL_PlayList = [ "ZpaUy4TnD_8", //★☆★【MMD】ままま式あぴミクさんでサイバーサンダーサイダー "I1womLtDYb8", //★☆★【MMD】Weekender Girl "y2oTcAtAsNc", //★★★★[ミクの日感謝祭 39's Giving Day] 恋スルVOC@LOID (feat. 初音ミク) / OSTER Project "zBNWup41idY", //★★★★[ミクの日感謝祭 39's Giving Day] StargazeR (feat. 初音ミク) / 骨盤P "MO-7YxoE-pc", //★★★★[ミクの日感謝祭 39's Giving Day] 裏表ラバーズ (feat. 初音ミク) / wowaka "gucD0aURXv0", //★★★★[ミクの日感謝祭 39's Giving Day] 愛言葉 (feat. 初音ミク) / DECO*27 "PUr15HBFVWE", //★【IA】メテオ【オリジナルPV】 "HE1sJfLkVjk", //★【MMD】 galaxias! ~IA~ "R5oekmftgMc", //★【再】IAさん達にgalaxias!を踊ってもらいました。[HD1080p] "6V_N3vAnauQ", //【VOCALOID MMD】Gravity=Reality【IA Model】 "0JglNR2k36o", //【VOCALOID IA】 Little HERO!! 【オリジナル】 "RMtZ_G-OwUs", //★☆★メランコリック試作1 "qyoAlh38Or0", //★☆★【MMD】トリノコシティ【Appearacne Miku】 "ZpaUy4TnD_8", //★☆★【MMD】ままま式あぴミクさんでサイバーサンダーサイダー "I1womLtDYb8", //★☆★【MMD】Weekender Girl "2eRgs6XJ-6g", //★★★★★【MMD】多重未来のカルテット~QUARTET THEME~ Tda式ミク・アペンド【HD】 "6E77Z7aqJCE", //★★★★★【MMD】ポーカーフェイス Tda式ミク・アペンド改変モデル【HD】 "sl17g1LGKdI", //★★★★★キャットフード - 初音ミク "q9bs1sDjzjc", //★★★★★【Hatsune Miku】 ODDS & ENDS + Mp3 Link "rqg4Eun7fgs", //★★★★★【初音ミク】「ミクの日大感謝祭」ダイジェスト映像 "5QJvzf0EarE", //★★★★★【MMD】 もう一度WAVEFILEを踊りたい 【第1回我家のレア様杯】 [HD1080p] "mlo4GN7lffg" //☆☆☆☆☆【初音ミク】「金の聖夜霜雪に朽ちて」PV ディレクターズカット版 ]; var YTinfo; var NTL_Language = "ja"; //【表示言語】 // var NTL_Tour=18; // 負の値のときは上記URL[/script/MoviePlayList.js]のプレイリストで表示する var NTL_Tour= -1; // 負の値のときは上記プレイリスト[NTL_PlayList]で表示する var NTL_Count = 0; var NTL_Check = 0; var NTL_Timer; var NTL_nDelete=0; var NTL_Element = new Array(0); //【divタグid】 var NTL_IDs = new Array(0); //【動画ID】 var NTL_Player; //【Playerオブジェクト】 var NTL_Duration; //【Duration】 //******************************************************* //【Initialize】 //******************************************************* function Proc() { var n = NTL_PlayList.length; if(NTL_Tour>=0) { n = playlist.tour[NTL_Tour].movie_data.length; NTL_PlayList = new Array(n); for(var i=0; i<n; i++) { NTL_PlayList[i] = playlist.tour[NTL_Tour].movie_data[i].movie_id; } } InitializeYouTubeInformation(); InitializeDivTags(); SendRequest(); } //******************************************************* //【SendRequest】 //******************************************************* function SendRequest() { clearTimeout(NTL_Timer); RequestYouTubeMovieRecord(NTL_PlayList[NTL_Count]); NTL_Count++; if(NTL_Count<NTL_PlayList.length) { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>只今、No." + NTL_Count.toString() + "のデータを要求中</font></H2>"; NTL_Timer = setTimeout( SendRequest, 50 ); } else { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>巡回結果の検証を行っています</font></H2>"; NTL_Timer = setTimeout( CheckResult, 3000 ); } } //******************************************************* //【Initialize Div Tags】 //******************************************************* function InitializeDivTags() { var rem = ""; for(var i=0; i<NTL_PlayList.length; i++) { rem += "<table width='1000px' border='1' cellpadding='0' cellspacing='0' style='border-collapse: collapse; border-width: 0'>" + "<tr><td width='1000px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Title" + i.toString() + "' name='Title" + i.toString() + "'></div>" + " </td>" + "</tr>" + "</table>" + "<table width='1000px' border='1' cellpadding='0' cellspacing='0' style='border-collapse: collapse; border-width: 0'>" + "<tr><td width='130px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Icon" + i.toString() + "' name='Icon" + i.toString() + "'></div>" + " </td>" + " <td width='870px' style='border-style: none; border-width: medium; line-height:120%' height='1' align='left' valign='top'>" + " <div id='Info" + i.toString() + "' name='Infon" + i.toString() + "'></div>" + " </td>" + "</tr>" + "</table>"; } document.getElementById("BGMList").innerHTML += rem; for(var i=0; i<NTL_PlayList.length; i++) { document.getElementById('Title' + i.toString()).innerHTML = "No." + i.toString() + " 動画ID[ <a title='【YouTubeの動画ページ】' href='http://www.youtube.com/watch?v=" + NTL_PlayList[i] + "' target='_blank'>" + NTL_PlayList[i] + "</a> ]"; document.getElementById('Icon' + i.toString()).innerHTML = "<img border='0' src='/b/ZZZZZZZZZZZ.jpg' width='120px' height='90px' />"; document.getElementById('Info' + i.toString()).innerHTML = "<font face='Times New Roman' size='4' color='red'><b>この動画は限定公開または非公開の動画であるか、<br>あるいは削除されている可能性があります。</b></font>"; } } //%%% Google YouTube Data API %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% //******************************************************* //【Initialize YouTube Information】 //******************************************************* function InitializeYouTubeInformation() { YTinfo = new Array(NTL_PlayList.length); var Obj = new Object(); for(var i=0; i<YTinfo.length; i++) { YTinfo[i] = { "id": NTL_PlayList[i], "AuthorName": "", "Published": "", "Title": "", "Thumbnail": Obj, "ViewCount": 0, "FavoriteCount": 0, "Duration": 0 }; } } //******************************************************* //【Request YouTube Movie Record】callback ==> GetYouTubeMovieRecord //******************************************************* function RequestYouTubeMovieRecord(id) { //【GData_JSON_Request】指定動画IDの動画情報をJSONデータ形式で要求する var STag = document.createElement("script"); //【scriptタグ要素を用意してJSONを要求するURLをsrcとする】 STag.charset = "utf-8"; // エンコードをutf-8とし、型をテキスト/JavaScriptとする STag.type = "text/javascript"; // JSONデータ受取の為のfunction[GetYouTubeMovieRecord]をcallbackで定義する STag.src = "http://gdata.youtube.com/feeds/api/videos?alt=json&q=" + id + "&callback=GetYouTubeMovieRecord"; document.body.appendChild(STag); //【上記JSONデータを要求する要素をbodyにappendする】 } //******************************************************* //【Get YouTube Movie Record】【callback】 //******************************************************* //指定動画IDの動画情報をJSONデータ形式で受け取る function GetYouTubeMovieRecord(Feed) { //【Googleから返送されたJSONデータを構造体データとして引き数Feedで受け取る】 if(Feed.feed.entry[0]==undefined) return; var Thumbnail = { url:"", height:0, width:0 }; Thumbnail.url = Feed.feed.entry[0].media$group.media$thumbnail[0].url; //【】url Thumbnail.height = Feed.feed.entry[0].media$group.media$thumbnail[0].height; //【】height Thumbnail.width = Feed.feed.entry[0].media$group.media$thumbnail[0].width; //【】width var s = Thumbnail.url.split("/"); var id = s[4]; for(var i=0; i<YTinfo.length; i++) { if(id==YTinfo[i].id) { YTinfo[i].AuthorName = Feed.feed.entry[0].author[0].name.$t; //【動画所有者名】YouTubeチャンネルの名称 YTinfo[i].Title = Feed.feed.entry[0].title.$t; //【題名】 YTinfo[i].ViewCount = Feed.feed.entry[0].yt$statistics.viewCount; //【再生回数】 (他に評価や動画説明等のデータもある。) YTinfo[i].FavoriteCount = Feed.feed.entry[0].yt$statistics.favoriteCount; //【評価】 YTinfo[i].Duration = Feed.feed.entry[0].media$group.yt$duration.seconds; //【動画再生時間】【秒】 YTinfo[i].Published = Feed.feed.entry[0].published.$t; //【アップロード日時】 YTinfo[i].Published = YTinfo[i].Published.replace(/-/g, "/"); // YTinfo[i].Published = YTinfo[i].Published.replace(/T/, " "); // YTinfo[i].Thumbnail = Thumbnail; // url, height, width, time //【表示内容更新】 var element1 = "Icon" + i.toString(); var element2 = "Info" + i.toString(); //***************************************************** //【サムネール表示】 //***************************************************** document.getElementById(element1).innerHTML = "<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + "<img border='0' src='" + YTinfo[i].Thumbnail.url + "' width='120px' height='90px' /></a>"; //***************************************************** //【動画情報の表示】 //***************************************************** var rem = ""; if (NTL_Language == 'ja') { rem += "【タイトル】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].Title +"</a><br>"; rem += "【所有者】<a title='YouTubeの所有者のチャンネルに遷移します。' href='http://www.youtube.com/user/" + YTinfo[i].AuthorName + "' target='_blank'>" + YTinfo[i].AuthorName +"</a> "; rem += "【動画ID】<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].id + "</a> "; rem += "【記録時間】" + YTinfo[i].Duration + "【秒】<br>"; rem += "【アップロード日時】" + YTinfo[i].Published.substring(0,16) + " "; rem += "【再生回数】" + YTinfo[i].ViewCount + " "; rem += "【お気に入り登録】" + YTinfo[i].FavoriteCount + "<br>"; } else { // 'en': 英語表示モード rem += "【Title】<a title='Jump to Movie Page in YouTube' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].Title +"</a><br>"; rem += "【YouTube_Movie_ID】<a title='Jump to Movie Page in YouTube' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + YTinfo[i].id + "</a><br>"; rem += "【Owner】<a title='Jump to Owner_Channel in YouTube' href='http://www.youtube.com/user/" + YTinfo[i].AuthorName + "' target='_blank'>" + YTinfo[i].AuthorName +"</a><br>"; rem += "【Published Date】" + YTinfo[i].Published.substring(0,16) +"<br>"; rem += "【View Count】" + YTinfo[i].ViewCount + " 【Favorite Count】" + YTinfo[i].FavoriteCount + "<br>"; } document.getElementById(element2).innerHTML = rem; break; } } } //******************************************************* //【CheckResult】 //******************************************************* function CheckResult() { clearTimeout(NTL_Timer); //【タイマークリア】 var element1, element2; //【動画サムネールと情報欄のdivタグid】 NTL_Count=0; //【動画情報が返送されなかった動画idを調べる】 for(var i=0; i<NTL_PlayList.length; i++) { if((YTinfo[i].Title=="")&&(YTinfo[i].AuthorName=="")&&(YTinfo[i].Published=="")) { element1 = "Icon" + i.toString(); element2 = "Info" + i.toString(); document.getElementById(element1).innerHTML = "<a title='YouTubeの動画ページに遷移します。' href='http://www.youtube.com/watch?v=" + YTinfo[i].id + "' target='_blank'>" + "<img border='0' src='http://i1.ytimg.com/vi/" + YTinfo[i].id + "/default.jpg' alt='Error404' onerror='/b/p.gif' width='120px' height='90px' /></a><br><br>"; NTL_IDs.push(YTinfo[i].id); //【動画IDを保存】 NTL_Element.push(element2); //【divタグidを保存】 NTL_Count++; } } if(NTL_Count!=0) { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>削除された可能性のある動画が" + NTL_Count.toString() + "件見つかりました</font></H2>"; //NTL_Count個のPlayerを起動する NTL_Player = Array(NTL_Count); NTL_Duration = Array(NTL_Count); for(i=0; i<NTL_Count; i++) { NTL_LoadPlayer(NTL_Element[i], 585, 370, NTL_IDs[i], i); //【情報欄に動画を埋め込む】 NTL_Duration[i] = -1; } } else { document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>削除された動画はありませんでした</font></H2>"; } } //******************************************************************************* //【準備完了】【SWFobjectを使ったYouTube Player】 //******************************************************************************* function onYouTubePlayerReady(playerId) { //【playerId:0,1,2,・・・・】 NTL_Player[Number(playerId)] = document.getElementById("ytPlayer"+playerId); NTL_Duration[Number(playerId)] = NTL_Player[playerId].getDuration(); //【YouTubeからの読込タイムラグのせいで初回では0であるかも知れない】 NTL_Check++; if(NTL_Count==NTL_Check) { //【全てのPlayerの準備が完了した】 NTL_Timer = setTimeout(CheckDuration, 500); //【0.5秒毎にcallback】 } } //******************************************************************************* //【Playerを初期化・表示】【SWFobjectを使ったYouTube Player】 //******************************************************************************* function NTL_LoadPlayer(element, yt_width, yt_height, yt_id, num) { var params = { allowScriptAccess: "always" }; var atts = { id: "ytPlayer"+num.toString() }; swfobject.embedSWF("http://www.youtube.com/v/" + yt_id + "?enablejsapi=1&start=1&playerapiid="+num.toString(), element, yt_width.toString(), yt_height.toString(), "8", null, null, params, atts); } //******************************************************************************* //【CheckDuration】【SWFobjectを使ったYouTube Player】 //******************************************************************************* function CheckDuration() { var msg = ""; clearTimeout(NTL_Timer); NTL_nDelete = 0; for(var i=0; i<NTL_Count; i++) { NTL_Duration[i] = NTL_Player[i].getDuration(); if(NTL_Duration[i]==0) { NTL_nDelete++; msg += "<H2><font face='Times New Roman' color='red'>動画ID[ " + NTL_IDs[i] + " ]が削除されました</font></H2>"; } } document.getElementById("ExecInfo").innerHTML = "<H2><font face='Times New Roman' color='red'>削除された動画は" + NTL_nDelete.toString() + "件と考えられます</font></H2>"; document.getElementById("ExecInfo").innerHTML += msg; NTL_Timer = setTimeout(CheckDuration, 500); //【0.5秒毎にcallback】 } //******************************************************************************* //【NTL_YTPlayer】 // ≪オプション≫ ループ再生:loop=1 自動再生:autoplay=1 透過属性:wmode=transparent // ○Google Chrome, IE, Opera, FireFox, Safari //******************************************************************************* function NTL_YTPlayer(element, yt_width, yt_height, yt_id) { var obj = document.createElement("iframe"); obj.setAttribute("frameBorder","0"); obj.width = yt_width; obj.height = yt_height; obj.src = "http://www.youtube.com/embed/" + yt_id; // + "?autoplay=1&wmode=transparent"; document.getElementById(element).appendChild(obj); } window.onload = function () { Proc(); } </script> </head> <body background="/b/Background2.jpg"> <font face="Times New Roman" size="3"> <img src="/b/face1.png" width="100px"> <font color="pink">powered by</font> <a title="私設研究所Neo-Tech-Lab" href="http://www.neo-tech-lab.co.uk/"><font face="Times New Roman"><b><i><font color="black" size="5"><font color="red">Neo</font>-<font color="green">Tech</font>-<font color="blue">Lab</font>.<font color="brown">com</font></font></i></b></font></a><br> <font color="yellow" size="4"> ●このページで埋め込み利用しているYouTubeの動画のリストです。<br> ●当サイト自体には動画配信能力はなく、今表示中の動画は全てYouTubeから直接配信されています。<br> ●著作権はそれぞれの動画をYouTubeにアップロードした人に帰属しています。<br> 特にPerfumeをはじめとする実写動画は<a title="『Perfume』チャンネル" href="http://www.youtube.com/user/Perfume" target="_blank"><font color="white">『Perfume』公式チャンネル</font></a>(http://www.youtube.com/user/Perfume)と<br> <a title="『徳間ジャパン』さんのチャンネル" href="http://www.youtube.com/user/tokumajapan" target="_blank"><font color="white">『徳間ジャパン』さんのチャンネル</font></a>(http://www.youtube.com/user/tokumajapan)にアップロードされているものを利用しています。<br> ●当サイトのウェブ・エージェント'ミク'が、YouTubeの動画ページを1日に2回巡回して再生リストを管理しています。<br> ミクは参照元の動画が削除された事を検出すると自動的に再生リストからその動画IDを削除します。<br> ●最初の10曲は動画ツアー19番から実行されます。以降は動画ツアー18番に変更されます。<br> ●'ミク'のYouTube動画ページ巡回は、リンク繋がりによる『新曲探索』の目的も兼ねています。<br> あとは'ミク'にどうやって曲を評価させるか試行錯誤中なのですが、これはなかなかむずかしい問題ですね。<br> </font> <div id="ExecInfo" name="ExecInfo"><H2><font face='Times New Roman' color='red'>只今、YouTubeにデータの要求を開始します。</font></H2></div><br> <div id="BGMList" name="BGMList" style="width:1024px"> </div> </font> </body> </html> |