JSでビデオブロードキャストを作成する

こんにちは、habrachitatel様。

今日は、HTML5 / JSとNodeJS、およびPHPを使用して、Webカメラからの画像のライブブロードキャストを整理する方法を説明します。



この記事では、かなり大量のコードを観察しています。 また、この記事は専門家よりも初心者のWeb開発者に焦点を当てています。



クライアント部


最初に、 navigator.getUserMediaからのストリームがコピーされる「video」タイプの要素を作成する必要があります。また、送信のために画像が取得されるキャンバスも作成する必要があります。



<video autoplay id="vid" style="display:none;"></video> <canvas id="canvas" width="640" height="480" style="border:1px solid #d3d3d3;"></canvas><br>
      
      







次に、ストリームをgetUserMediaからビデオに向ける必要があります。



 var video = document.querySelector("#vid"), canvas = document.querySelector('#canvas'), ctx = canvas.getContext('2d'), localMediaStream = null, onCameraFail = function (e) { console.log('Camera did not work.', e); //   ,     }; navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia; window.URL = window.URL || window.webkitURL; navigator.getUserMedia({video: true}, function(stream) { video.src = window.URL.createObjectURL(stream); localMediaStream = stream; }, onCameraFail);
      
      







さて、この段階で、ビデオストリームは「ビデオ」タグに複製されますが、このタグは表示されません。 次に、画像を絶えずキャンバスにコピーする必要があります。 これを行うには、コピープロシージャを呼び出すタイマーを設定し、それに応じてコピープロシージャ自体を設定します。



 cameraInterval = setInterval(function(){ snapshot();}, 1); function snapshot(){ if(localMediaStream){ ctx.drawImage(video, 0, 0); } }
      
      







さて、あなたは自分を見ることができますが、データはまだどこにも送信されていません。 データを送信するには、すべてが同期され、ユーザーがブロードキャストに同意することを確認する必要があります。そのため、ストリームを有効または無効にするボタンをいくつか追加します。



 <button onclick="startBroadcasting()">Start Broadcasting</button> <button onclick="stopBroadcasting()">Stop Broadcasting</button>
      
      







そして、サーバーにデータを送信する手順を作成します。

しかし、どのようなデータですか? この問題を解決するには、キャンバス上のすべてのbase64圧縮を使用し、それに応じてこの行をサーバーに送信します。



 var isBroadcasting = false, broadcastingTimer; function sendSnapshot(){ if(localMediaStream && !isBroadcasting){ isBroadcasting = true; $.post("/", { p: "new", text: ctx.canvas.toDataURL("image/webp", quality); // quality -  (float) }, function(result){ console.log(result); //  ,  -    isBroadcasting = false; } ); } } //         function startBroadcasting(){ broadcastingTimer = setInterval(sendSnapshot, 1); } function stopBroadcasting(){ clearInterval(broadcastingTimer); }
      
      







ブロードキャストのクライアント部分は終了しました。



サーバー側(ノードJS)


このようなアプリケーションには、高度な機能やサーバーフレームワークは必要ありません。 サーバーは、http.createServer関数を使用して作成されます。

ここでの主なことは、投稿リクエストが到着した場合にハンドラを追加することです。



 var qs = require('querystring'); var imageData = ""; var myId = 1; /*   */ if(req.method == "POST"){ var fullBody = ""; req.on('data', function(chunk){ fullBody += chunk.toString(); }); req.on('end', function(){ res.writeHead(200, {'Content-Type': 'text/html'}); var POST = qs.parse(fullBody); if(POST["p"] == "new"){ //   imageData = POST["text"]; myId += 1; res.write(imageData); }else if(POST["p"] == "ajax"){ if(myId > parseInt(POST["last"])){ if(typeof(imageData) != "undefined"){ res.write(document.body.innerHTML = ('<img src=" + '"' + imageData + '"' + "/>');" + "\n"); res.write("last_message_id = " + myId + ";"); } } } res.end(); }); }else{ /*    ,   . */}
      
      







同様にphpの場合:



PHPコード
 if($_GET['p'] == "ajax"){ Header("Cache-Control: no-cache, must-revalidate"); Header("Pragma: no-cache"); Header("Content-Type: text/javascript; charset=windows-1251"); $file = file("monitor_id.txt"); $id = $file[0]; if($id > $_GET['last']){ $text_file = file("monitor_command.txt"); $count = count($text_file); $last = $id; echo "var main = $('#main'); \n"; for($i = 0; $i < 1; $i++){ $s = $text_file[$i]; while(strpos($s, chr(92)) !== false){ $s = str_replace(chr(92), "", $s); } echo $s; } echo "\n"; echo "last_message_id = $id;"; } }elseif((isset($_GET['p']) && $_GET['p'] == "new") || (isset($_POST['p']))){ $file = file("monitor_id.txt"); $id = $file[0]; $fh = fopen("monitor_command.txt", "w+"); $get_text = $_POST['text']; $gt = $get_text; while(strpos($get_text, "\r\n") !== false){ $get_text = str_replace("\r\n", "</br>", $get_text); } fwrite($fh, "document.body.innerHTML = ('<img src=".'"'.".$get_text.'"'."/>);\n"); fclose($fh); $fhn = fopen("monitor_id.txt", "w+"); fwrite($fhn, $id + 1); fclose($fhn); echo $get_text; }
      
      









クライアント側(ビューブロードキャスト)


奇妙なことに、クライアント部分は非常にシンプルで、サーバーからのコードの実行のみが必要です。

 var last_message_id = 0, load_in_process = false; function Load() { if(!load_in_process) { load_in_process = true; $.post("/", { p: "ajax", last: last_message_id, version: version }, function (result) { eval(result); load_in_process = false; }); } } var loadInterval = setInterval(Load, 1);
      
      







おわりに


今日は、html5 / jsを使用して一方向のビデオ放送を整理するための簡単なサービスを作成しました。 これまでのところ、このソリューションは通常の圧縮がないため非常に速く動作せず、すべての画像処理操作はクライアントでのみ実行できるため、フレームレートが低下し、観察され始めることに注意してくださいハングします。」



しかし、このかなり単純な例は、html5がフラッシュからそれほど遠くないこと、および多くのことの実装が可能になることの単なる証拠です。



ご清聴ありがとうございました!



All Articles