追記
youtubeライブに2021年ごろ?に便利なアンケート機能が追加されました。
追記終わり
さてタンバリンさんのツールが動いているのを見ました。
あれは過去のコメントも保存しているようですね。それどうだろうなぁ?
アンケート機能があるようですね。便利そうですね。
じゃあYouTubeの生放送のチャットを使ってアンケートを作ってみましょ
ニコニコのようなアンケート機能が視聴者には匿名ですしやりやすい思うのですが、
YouTubeにはそのような機能はないのでお試しに作ってみました。
検索すると、YouTubeでアンケートカードというものもあるらしいですが、
生放送には対応していないのかな?誰か作ってそうですけどねぇ
仕様は、
・投票項目を入力できる
・投票開始ボタンが押されてからのチャットのみを投票の対象とする
・アンケート中に投票数が確認できる
・IDで同じ人からの投票を弾く(途中で投票先の変更はダメ)
・投票終了時の結果を円グラフで表示する。
※スーパーチャットには今回未対応
苦労した所は、
ほんとはしちゃいけないだろうけど、PHPのコード部分に無限ループする部分があります。
ブラウザがChrome
かつ
sessionを使用した場合
スクリプトが終了していないのと次のページ遷移できない
という問題があるようで解決に時間がすごくかかりました。
(IE,FireFoxは停止しなくても遷移しました。)
解決策として正しいかわからないですが、
window.stop();
によってブラウザの中止ボタンの機能によりスクリプトを停止して解決してます。
そしたら今度は、IEがwindow.stop()関数に対応していないので使用ブラウザの判断をして
回避しています。
これでIE,Chrome,FireFoxで動いているのを確認しました。
3ページ分のコードをいつものフォルダ(C:\xampp\htdocs)に配置して
ブラウザ上で
http://localhost/vote1.php
とすれば使用できます。
いままでのやってきたことを組み合わせたようなもんです。
外見はこんな感じです。
見れば動きはなんとかくわかるでしょう。
1ページ目
例は雑に1文字ずつになっていましが、ちゃんと指定できます。
これは投票先を「あ」「い」「う」にしています。
本来は好きなお菓子の名前などちゃんとしたものを入れましょう。
2ページ目
投票項目が見えるようにしています。
この画像の動作では「あ」「い」「う」のワードを含むチャットを「投票した」
としていますが、
一致でもいいし、
投票項目のワードが長いと入力が大変だと思い「#1」~「#3」でもコードをいじればできます。(数字だけでもいいでしょう)
何も表示されないと寂しいのでチャットと現在の投票数を表示しています。
アンケートを打ち切る場合は投票終了ボタンを押します。
3ページ目
HighChartsを使いアンケート結果が円グラフで表示されます。
それぞれの結果を%と票数も全部載せです。
再びアンケートをやる場合は1ページに目から開始してください。
コードです。
1ページ目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <!DOCTYPE html> < html lang = "ja"> < head > < meta charset = "utf-8"> < title >アンケート項目設定</ title > </ head > < body > < form action = "vote2.php" method="post"> < p >投票項目を入力してください< br > < textarea name="keyword" cols="60" rows="6"></ textarea > < br > < input type = "submit" value="投票開始" name="button1"> </ form > </ body > </ html > |
form部分だけなので注釈はありません。
php部分が1行もないのにファイル名がphpですね。。。
2ページ目
①にはAPIキー、②には今回は生放送中の動画のidを入れます。
https://www.youtube.com/watch?v=xxxxxxxxxxx
のxxxxxxxxxxxの文字列のことです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | <!DOCTYPE html> <html lang = "ja"> <head> <meta charset = "utf-8"> <title>アンケート中</title> <script language="javascript" type="text/javascript"> function OnButtonClick() { var userAgent = window.navigator.userAgent.toLowerCase(); console.log(userAgent); if (userAgent.indexOf('msie') != -1 || userAgent.indexOf('trident') != -1 ) { //IEは何もしない } else { window.stop(); } document.frm.submit(); return false; } </script> </head> <body> <style> t0 {color: blue; font-size:16px;} </style> <form name="frm" action = "vote3.php" method="post"> <p>投票項目 <input type="button" onclick="OnButtonClick()" value="投票終了" name="button2"> </p> </form> <?php session_start(); session_unset(); set_time_limit(60*60); //タイムアウト時間を60分に変更 if (isset( $_POST ["button1"])) { if ( $_POST ["keyword"] != "") { //投票項目の作成 $str = str_replace ( array ("\r\n","\r","\n"), "\n", $_POST ["keyword"]); $tmplist = explode ("\n", $str ); $length = count ( $tmplist ); $keylist = array (); for ( $i =0; $i < $length ; $i ++) { if ( $tmplist [ $i ] != "") { array_push ( $keylist , $tmplist [ $i ]); } } //投票数をクリア $cnt = array_fill (0, count ( $keylist ),0); //投票先を表示 foreach ( $keylist as $t => $keyword ) { $chkkey = "#".((int) $t +1) .": ". $keyword ; print_r( $chkkey ); echo "<br>"; } echo "<hr>"; //セッションに保存する(初期化) $_SESSION ["chart"] = 0; foreach ( $keylist as $k => $keyword ) { $_SESSION ["key". $k ] = $keyword ; $_SESSION ["cnt". $k ] = $cnt [ $k ]; } $_SESSION ["num"] = count ( $keylist ); } else { print_r("投票項目をいれてください"); goto end ; } } else { print_r("エラー"); goto end ; } $apikey = "①"; $videoId = "②"; //ChatIdの取得 $search_api ="https: //www.googleapis.com/youtube/v3/videos?part=liveStreamingDetails&id=" . $videoId ."&key=" . $apikey; $search_contents = file_get_contents ( $search_api ); $search_json = json_decode( $search_contents ,true); $ChatId = $search_json ["items"][0]["liveStreamingDetails"]["activeLiveChatId"]; //ChatIdからliveChatにアクセス用のURL $search_api ="https: //www.googleapis.com/youtube/v3/liveChat/messages?part=snippet,authorDetails&liveChatId=" . $ChatId ."&key=" . $apikey; $idlist = array (); //回答者のIDリストのクリア $next = ""; $url = $search_api ; $skip = 0; while (1) { if ( $next ) { $url = $search_api . "&pageToken=" . $next ; } if ( $search_contents = @ file_get_contents ( $url )) { $search_json = json_decode( $search_contents ,true); $time_start = microtime(true); foreach ( $search_json ["items"] as $k => $data ) { //初回は過去データなのでスキップ if ( $skip == 0) { $skip = 1; break ; } $text = $data ["snippet"]["displayMessage"]; print_r( $text ); echo "<br>"; $trgid = $data ["authorDetails"]["channelId"]; foreach ( $keylist as $t => $keyword ) { //$keyword = "#".((int)$t+1); //if($text == $keyword) //if($text == "#".((int)$t+1)) if ( strpos ( $text , $keyword ) === false){} else { if (in_array( $trgid , $idlist ) == false) //重複者チェック { array_push ( $idlist , $trgid ); $cnt [ $t ] = $cnt [ $t ] + 1; //セッションの値を更新する $_SESSION ["cnt". $t ] = $cnt [ $t ]; } break ; } } } $next = empty ( $search_json ["nextPageToken"])? 0 : $search_json ["nextPageToken"]; $delay = $search_json ["pollingIntervalMillis"]/1000.0; $time = microtime(true) - $time_start ; echo "<t0>現在の投票数" . count ( $idlist ) . "</t0>"; echo "<br>"; //ブラウザに少しずつ表示するため必要 ob_flush(); flush (); do { $time = microtime(true) - $time_start ; usleep(100); //0.1ms待ち } while ( $time < $delay ); } } end : ?> </body> </html> |
注釈として
7行目から22行目あたりがスクリプトを停止して3ページ目へ遷移させる部分です。
48行目から59行目あたりが1ページ目の入力を分解して投票項目を作成しています。
空の行を無視します。
94行から下は基本的にはチャット表示のコードの改造です。
130行目あたりは、APIが初回の入力はボタンを押したものの過去のチャットとなりますのでスキップする処理です。
142行から145行あたりは、一致するか、含むにするか、#nの一致にするかです。
好きなコードを選んでください。
148行目から156行目はまだ投票していないIDでの投票一致の場合、票として数えているところです。
3ページ目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | <!DOCTYPE html> < html lang = "ja"> < head > < meta charset = "utf-8"> < title >アンケート結果</ title > < script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></ script > < script type="text/javascript" src="https://code.highcharts.com/highcharts.js"></ script > < script type="text/javascript" src="https://code.highcharts.com/modules/exporting.js"></ script > </ head > < body > < form > < div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></ div > </ form > <? php session_start(); if($_SESSION["num"] !="") { $_SESSION["chart"] = 1; } else { print_r("エラー"); } ?> < script > var phpSession = <? php echo json_encode($_SESSION); ?>; if(phpSession["chart"] ==1) { Highcharts.chart('container', { chart: { animation: Highcharts.svg, // don't animate in old IE plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false, type: 'pie' }, title: { text: 'アンケート結果' }, tooltip: { pointFormat: '{series.name}: < b >{point.percentage:.1f}%</ b >' }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: true, format: '< b >{point.name}</ b >: {point.percentage:.1f} % :{point.y}票', style: { color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black' } } } }, series: [{ name: 'vote', colorByPoint: true, data: (function () { var data = [],i; for( i=0;i< phpSession ["num"];i+=1) { data.push({ name: "#"+(i+1)+": "+phpSession["key" + i], y: phpSession["cnt"+i] }); } return data; }()) }] }); } </script> </ body > </ html > |
注釈として
Highchartsの円グラフの例 を改造し、2ページ目の結果を入力としています。
33行目でPHPから_SESSIONのデータを受け取り、
それを68行目から78行目で使用しています。
ちゃんと勉強せず、行き当たりばったりで作っているから苦労する。
いままでのコードもformやhead、bodyの対応がよくなかったようだ。
WEB系の基本勉強してないものなぁ。
ユーチューブのライブ配信でのアンケートとてもいい機能だと思います。
返信削除私も眠たいお粥さんのブログを元に作ってみようと思います。
今後も拝見させていただきますのでよろしくお願いお願いします。
何かしらの参考になれたらうれしいです。 ( ´ ▽ ` )ノ
削除vote2の129にエラーが出るんですが原因がわかりません;;
返信削除Parse error: syntax error, unexpected ‘ ‘ (T_STRING)
こちらのミスですね・・・
返信削除vote2の128と129行のあたりに全角のスペースがありました。
これだとエラーがでます。
削除すればいけるはずです。