<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:series="http://organizeseries.com/"
	>

<channel>
	<title>PeerJS &#8211; HTML5Experts.jp</title>
	<atom:link href="/tag/peerjs/feed/" rel="self" type="application/rss+xml" />
	<link>https://html5experts.jp</link>
	<description>日本に、もっとエキスパートを。</description>
	<lastBuildDate>Sat, 07 Jul 2018 03:14:05 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.7.19</generator>
	<item>
		<title>SpeechRecognitionとWebRTCでつながる新感覚言葉遊び「コトバツナギ」の技術全て見せます！</title>
		<link>/foka/9979/</link>
		<pubDate>Tue, 26 Aug 2014 00:00:15 +0000</pubDate>
		<dc:creator><![CDATA[藤岡宏和]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[5jcup]]></category>
		<category><![CDATA[PeerJS]]></category>
		<category><![CDATA[SpeechRecognition]]></category>
		<category><![CDATA[WebRTC]]></category>

		<guid isPermaLink="false">/?p=9979</guid>
		<description><![CDATA[連載： HTML5 Japan Cup 特集 (2)「コトバツナギ」というWebコンテンツを作成し、HTML5 Japan Cup 2014で最優秀賞を頂きました。コトバツナギは、SpeechRecognitionとWe...]]></description>
				<content:encoded><![CDATA[<div class="seriesmeta">連載： <a href="https://html5experts.jp/series/5jcup-2/" class="series-207" title="HTML5 Japan Cup 特集" data-wpel-link="internal">HTML5 Japan Cup 特集</a> (2)</div><p>「<a href="https://kotoba.tsukuenoue.com/" title="コトバツナギ" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">コトバツナギ</a>」というWebコンテンツを作成し、HTML5 Japan Cup 2014で最優秀賞を頂きました。コトバツナギは、SpeechRecognitionとWebRTCを軸にしたマルチユーザーコンテンツです。このコンテンツで使っている主な技術の解説をしたいと思います。</p>

<h2>概要</h2>

<p><a href="https://kotoba.tsukuenoue.com/" title="コトバツナギ" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">コトバツナギ</a>は、声に出して声で遊ぶマルチユーザーコトバアソビゲームです。</p>

<p><img src="/wp-content/uploads/2014/08/capture_01_enter.png" alt="コトバツナギ" width="600" height="382" class="aligncenter size-full wp-image-10009" srcset="/wp-content/uploads/2014/08/capture_01_enter.png 600w, /wp-content/uploads/2014/08/capture_01_enter-300x191.png 300w, /wp-content/uploads/2014/08/capture_01_enter-207x131.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p><img src="/wp-content/uploads/2014/08/capture_sp2.png" alt="コトバツナギ" width="285" height="517" class="aligncenter size-full wp-image-10029" srcset="/wp-content/uploads/2014/08/capture_sp2.png 285w, /wp-content/uploads/2014/08/capture_sp2-165x300.png 165w, /wp-content/uploads/2014/08/capture_sp2-114x207.png 114w" sizes="(max-width: 285px) 100vw, 285px" /></p>

<p>PCサイトを開き、スマートフォンを皆で持って集まって遊ぶゲームになっています。スマートフォンの代わりにマイク機能付きのノートPCでも可です。</p>

<p>WebRTCとwebkitSpeechRecognitionを使っているため、2014年8月の時点ではPC・スマホともにChromeブラウザのみ対応です。iOSのChromeはWebRTCとwebkitSpeechRecognitionに非対応のため不可ですが、MacのChromeは動作します。一人でも遊べます。</p>

<p>動作環境が限られるので遊べないユーザーがいる場合もあると思い、デモ動画も用意しました。</p>

<p>
<!-- iframe plugin v.4.3 wordpress.org/plugins/iframe/ -->
<iframe width="640" height="360" src="//www.youtube.com/embed/cTaC_h_ao_E" frameborder="0" 0="allowfullscreen" scrolling="yes" class="iframe-class"></iframe>
<br>
　解説文字無しの動画はこちら → [<a href="http://youtu.be/G6HGNISv4mo" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">http://youtu.be/G6HGNISv4mo</a>]</p>

<p>コトバツナギの主な技術をまとめると、</p>

<ul>
    <li>SSL</li>
    <li>WebRTC（getUserMedia）</li>
    <li>WebRTC（PeerJS）</li>
    <li>SpeechRecognition</li>
    <li>SpeechSynthesis</li>
    <li>Web Audio</li>
    <li>テキスト解析</li>
    <li>画像検索</li>
</ul>

<p>で、できてます。</p>

<p>次章より詳しく説明していきます。</p>

<h2>getUserMediaとSSL</h2>

<p>WebRTCでカメラ・マイク入力を利用可能にするgetUserMediaは、使用する度にブラウザに許可を得るダイアログが出てしまいます。このままだとゲームとして遊ぶには問題がありますが、httpsでアクセスできるようにすると回避できるため、SSLを導入しました。httpsの場合、アクセスしているドメインに対して最初に1回だけ許可すると、その後の許可は不要になります。（ブラウザを閉じても、設定をクリアするまで有効）</p>

<p><img src="/wp-content/uploads/2014/08/3f1c4e6aeb57ca113dda496e8aec5cb9.png" alt="マイク・カメラへのアクセス許可" width="250" height="394" class="aligncenter size-full wp-image-9998" srcset="/wp-content/uploads/2014/08/3f1c4e6aeb57ca113dda496e8aec5cb9.png 250w, /wp-content/uploads/2014/08/3f1c4e6aeb57ca113dda496e8aec5cb9-190x300.png 190w, /wp-content/uploads/2014/08/3f1c4e6aeb57ca113dda496e8aec5cb9-131x207.png 131w" sizes="(max-width: 250px) 100vw, 250px" /></p>

<p>コトバツナギでは、カメラ・マイクでそれぞれ許可ダイアログが出るので、最初に計2回の許可が必要になります。getUserMediaのvideo・audioを一度に扱えば一回で済みますが、マイク入力は使えるけどカメラが使えない（またはカメラの利用が嫌だ）という場合にも対応するため、このコンテンツではそれぞれの許可を分けました。</p>

<h2>PeerJS</h2>

<p>PCとスマートフォン間でWebRTCによる通信を実現するために<a href="http://peerjs.com/" title="PeerJS" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PeerJS</a>を利用しています。PeerJSは無料で使える<a href="http://peerjs.com/peerserver" title="http://peerjs.com/peerserver" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PeerServer Cloud service</a>を用意してくれていますがSSLに対応していません。今回は、レンタルしているVPSにPeerServerをインストールして、下記のサーバーサイドjavascriptをnode.jsのforeverコマンドで起動し、PeerServerを立てました。</p>

<p></p><pre class="crayon-plain-tag">var fs = require('fs');
var PeerServer = require('peer').PeerServer;
var server = new PeerServer({
	port: [ポート番号を指定します],
	path: '[パスを指定したい場合は記述します]',
	ssl: {
		key: fs.readFileSync('[sslのkeyファイルのパスが入ります]'),
		certificate: fs.readFileSync('[sslのcrtファイルのパスが入ります]')
	}
});</pre><p></p>

<h2>アイコトバでハジメル</h2>

<p>PCとスマートフォンを接続する際に、数字入力や文字入力をするコンテンツがよくありますが、その方法はあまり味気ないと以前より思っていたので、このコンテンツでは別の方法を検討しました。タップと声だけで遊べるコンテンツにしたかったので、アイコトバを声に出して言ってから始める仕組みにしています。</p>

<p><img src="/wp-content/uploads/2014/08/capture_02_aikotob.png" alt="コトバツナギ：アイコトバでハジメル" width="600" height="382" class="aligncenter size-full wp-image-10010" srcset="/wp-content/uploads/2014/08/capture_02_aikotob.png 600w, /wp-content/uploads/2014/08/capture_02_aikotob-300x191.png 300w, /wp-content/uploads/2014/08/capture_02_aikotob-207x131.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p>コトバツナギではアイコトバやゲーム本編での音声認識に、webkitSpeechRecognitionを使ってます。アイコトバは予めいくつか用意しておいて、認識した音声を対応する数字に変換するという仕組みをとっています。</p>

<p></p><pre class="crayon-plain-tag">var recognition = new webkitSpeechRecognition();
recognition.maxAlternatives=1; //webkitSpeechRecognitionは複数の解析候補を出力してくれる場合があるが、このコンテンツでは一つだけに絞って使用。
recognition.onresult = function(event) {
	//音声認識の解析結果のテキスト
	var resultText=event.results[0][0].transcript;

	//resultTextを予め用意してあるリストに照合して、マッチしたら該当の数字に変換
}
recognition.start();</pre><p></p>

<p>なお、webkitSpeechRecognitionは、onresult以外に、onstart、onend、onaudiostart、onsoundstart、onspeechstart、onspeechend、onsoundend、onaudioend、onnomatch、onerrorという多くのイベントがあり、必要に応じて使い分けることが重要になります。</p>

<p>解析結果（上記resultText）を数字に変換したら、WebRTCのDataChannel（PeerJSのDataConnection）を利用してPC側のゲーム本体と通信します。</p>

<p></p><pre class="crayon-plain-tag">var peer = new Peer('[自分のID番号]', {host: '[PeerServerのhost]', port: ['ポート番号'], path: '[パスを指定してPeerServerを立ち上げた場合は記述]'});

var connect = peer.connect('[接続先のゲーム本体のID番号。このコンテンツでは、resultTextのテキストを数字に変換]');
connect.on('open', function(){
	//接続成功
}
connect.on('data', function(data){
	//接続先から送られてきたdataを処理
}</pre><p></p>

<p>数字入力や文字入力を使った方が動作は安定するのですが、あえてアイコトバを使うようにしたのは、声に出して遊ぶゲームであることをゲーム本編の前にユーザーに体験してもらい、確認・練習してもらうという意図があります。また、ゲーム本編の前にマイク入力の許可をさせておきたいという狙いもあります。</p>

<h2>ゲームモードの選択</h2>

<p>ゲームは「シリトリでアソブ」「レンソウでアソブ」の2つのモードで遊べるようにしています。</p>

<p><img src="/wp-content/uploads/2014/08/capture_03_modeselect.png" alt="コトバツナギ：モード選択" width="600" height="436" class="aligncenter size-full wp-image-10011" srcset="/wp-content/uploads/2014/08/capture_03_modeselect.png 600w, /wp-content/uploads/2014/08/capture_03_modeselect-300x218.png 300w, /wp-content/uploads/2014/08/capture_03_modeselect-207x150.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p>ゲームモードを選択する際、スマートフォンの場合にはタップ操作以外に端末を右か左に傾けることでも選べるようにしました。参加者みんなが体を傾けて選択している絵が作れたら面白いと思い、こういう機能をつけてます。</p>

<p>端末側の傾き検知は、以下のようになっています。
必要に応じて、傾き検知を開始・停止できるようにしておくと便利です。
</p><pre class="crayon-plain-tag">var peer = new Peer([自身のID番号],[PeerServer情報]);
var connect = peer.connect([ゲーム本体のID番号]);

//傾き検知が必要になったらstartDeviceMotion()を呼んでaddEventListenerする
var startDeviceMotion=function(){
	window.addEventListener('devicemotion',onDevicemotion);
};

//必要ない時に止められるようにしておく
var stopDeviceMotion=function(){
	window.removeEventListener('devicemotion',onDevicemotion);
};

//端末が傾くと呼ばれる。実際にはaddEventListnerしていると常に呼ばれ続ける。
var onDevicemotion=function(e){
	var gravity = e.accelerationIncludingGravity;
	var data={mode:"gravity",gx:gravity.x,gy:gravity.y};
	connect.send(data);
};</pre><p></p>

<p>ユーザーの端末傾き情報をゲーム側で受け取って、ゲームモード決定するところは以下のようになっています。
このコンテンツのように一対多で接続する場合は、WebRTCのDataChannel（PeerJSのDataConnection）を接続毎に保持して、各端末からの通信を処理します。
</p><pre class="crayon-plain-tag">var users=new Array();
var peer = new Peer([ゲーム本体のID番号],[PeerServer情報]);

peer.on('connection', function(connect) {
	//一対多の接続の場合は端末から接続がある毎に呼ばれるので、connectを保持しておく。
	//今回はUserクラスを用意してconnectを保持
	var user=new User(connect);
	users.push(user)
});

//各ユーザーがシリトリを選んでいるかレンソウを選んでいるか調べる
var cnt=0;
setInterval(function(){
	var siritoriSelected=0;
	var rensouSelected=0;

	for(var i=0;i&lt;users.length;i++){
		var selectmode=users[i].getSelectedMode();
		if(selectmode=="siritori"){
			siritoriSelected++;
		}else if(selectmode=="rensou"){
			rensouSelected++;
		}
	}
	
	//一定カウント後にどちらが多いかによってモード決定
	//（実際のゲームでは、全員の選択が落ち着くのを待ってからカウントしている）
	cnt++;
	if(cnt&gt;3){
		if(siritoriSelected&gt;=rensouSelected){
			//シリトリをはじめる
		}else{
			//レンソウをはじめる
		}
	}

},500);

//Userクラス
var User=function(connect){

	connect.on('data', function(data){
		//接続先の端末からいろいろな通信情報がここに送られるので、処理分岐できるようにしておく
		if(data.mode=="gravity"){
			onGravity(data);
		}
	});

	var onGravity=function(data){
		//data.gx、data.gyを元にアイコンを移動させる。
	};
	
	//画面右の方にいるか左の方にいるか調べてシリトリかレンソウを返す
	this.getSelectedMode=function(){
		var selectMode;
		if([左の方にいる場合]){
			selectMode= "siritori";
		} else{
			selectMode= "rensou";
		}
		return selectMode;
	}
}</pre><p></p>

<p>ゲームモード決定時には「シリトリでアソブ」か「レンソウでアソブ」と、ゲーム本体から声が出ますが、これは音声合成で発話しています。</p>

<p></p><pre class="crayon-plain-tag">var speech=new SpeechSynthesisUtterance();
speech.text="しりとりであそぶ";
speech.lang = "ja-JP";
speech.volume = 1;
speechSynthesis.speak(speech);//speechSynthesisはwindowが持っているオブジェクト</pre><p></p>

<h2>ゲーム本番</h2>

<p>シリトリゲーム、または連想ゲームでコトバをつないで遊びます。</p>

<p><img src="/wp-content/uploads/2014/08/capture_04_siritori.png" alt="コトバツナギ：ゲーム画面" width="600" height="382" class="aligncenter size-full wp-image-10012" srcset="/wp-content/uploads/2014/08/capture_04_siritori.png 600w, /wp-content/uploads/2014/08/capture_04_siritori-300x191.png 300w, /wp-content/uploads/2014/08/capture_04_siritori-207x131.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p>「シリトリでアソブ」のゲームの処理の流れを、利用している技術要素とともに図にしました。おおまかには、①～⑧の流れでコトバをつないでいきます。</p>

<p><img src="/wp-content/uploads/2014/08/0b3a21b2bd83d515cbe8e037e27b4195.png" alt="コトバツナギ：ゲームの処理の流れ" width="668" height="893" class="aligncenter size-full wp-image-10389" srcset="/wp-content/uploads/2014/08/0b3a21b2bd83d515cbe8e037e27b4195.png 478w, /wp-content/uploads/2014/08/0b3a21b2bd83d515cbe8e037e27b4195-224x300.png 224w, /wp-content/uploads/2014/08/0b3a21b2bd83d515cbe8e037e27b4195-154x207.png 154w" sizes="(max-width: 668px) 100vw, 668px" /></p>

<p>カメラの利用が許可されている場合、回答する度に毎回操作端末側のカメラでユーザーを撮影して、ゲーム本体に画像を送信しています（フロー②）。</p>

<p>また、ユーザーの操作端末がノートPCの場合は、回答の音声を端末側で録音し、blobデータとしてゲーム本体に送信しています。（フロー②、③）録音には<a href="https://github.com/mattdiamond/Recorderjs" title="recorder.js" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">recorder.js</a>を利用しました。recorder.jsはrecorderWorker.jsがセットになっており、Web Workerとして使う仕組みになっているようです。</p>

<p></p><pre class="crayon-plain-tag">var mediaStream;
var rec;
var audioContext=new AudioContext();

navigator.getUserMedia({audio:true}, 
	function(stream) {
		mediaStream=stream;
		var source = audioContext.createMediaStreamSource(stream);
		rec=new Recorder(source,{workerPath:[recorderWorker.jsまでのパス]"});
		rec.record();
	},
	function(err){
		//エラーの場合は何もしない。
		//スマホの場合はwebkitSpeechRecognitionと同時併用できないのでエラーになる。
	}
);

//録音終了したいタイミングで呼び出す
var recStop=function(){
	rec.stop();
	mediaStream.stop();

	//wav形式に変換したらonRecExportedを呼び出す
	rec.exportWAV(onRecExported);
};

//wav形式変換が完了するとblobデータが取得できる
var onRecExported=function(blob){
	//blobをWebRTCでゲーム本体に送信
};</pre><p></p>

<p>スマートフォンの場合、2014年8月現在ではSpeechRecognitionとgetUserMediaのaudioを同時に使えない仕様になっていたので、残念ながらスマートフォンの場合は録音を諦めました。（SpeechRecognitionを同時に使わなければ、スマートフォンでも録音することができます）</p>

<p>なお、ここで録音撮影した音声・画像は、ゲーム終了時に使います。</p>

<h2>ゲーム終了</h2>

<p>ゲーム終了すると、これまでつないだコトバが連続して再生されます。</p>

<p><img src="/wp-content/uploads/2014/08/capture_06_kotobachain.png" alt="コトバツナギ：ゲーム終了" width="600" height="382" class="aligncenter size-full wp-image-10013" srcset="/wp-content/uploads/2014/08/capture_06_kotobachain.png 600w, /wp-content/uploads/2014/08/capture_06_kotobachain-300x191.png 300w, /wp-content/uploads/2014/08/capture_06_kotobachain-207x131.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p><img src="/wp-content/uploads/2014/08/capture_07_last.png" alt="コトバツナギ：ゲーム終了" width="600" height="382" class="aligncenter size-full wp-image-10014" srcset="/wp-content/uploads/2014/08/capture_07_last.png 600w, /wp-content/uploads/2014/08/capture_07_last-300x191.png 300w, /wp-content/uploads/2014/08/capture_07_last-207x131.png 207w" sizes="(max-width: 600px) 100vw, 600px" /></p>

<p>getUserMediaのvideoが使える場合、終了時に流れる各コトバに表示されているユーザー画像は、ゲーム中に回答した時に、毎回撮影したものを表示しています。（ゲーム本番のフロー②で撮影）それぞれのコトバを発声した時に、どんな顔をしていたかがわかるようになっています。（ページ上部のデモ動画参照）</p>

<p>また、ノートPCを使って回答したユーザーのコトバの場合、ゲーム中に回答した時に、録音した音声を再生します。（ゲーム本番のフロー①②で録音）上述の通りスマートフォンでは音声録音がSpeechRecognitionと併用できないので、スマートフォンを使って回答したユーザーのコトバの場合は、音声合成で代用します。</p>

<p></p><pre class="crayon-plain-tag">var audioContext=new AudioContext();

//audioBlobはゲーム時に保存していたblobデータ
if(audioBlob){
	//audioContextはコンテンツ内でnewできる数に上限があるため、何度も同じ処理をする場合は、毎回newするのはなるべく避ける。
	//このコンテンツのように同時発音する可能性がなければ、AudioContextは再利用した方がnew上限エラーにならないので良いと思われる。
	if(!audioContext){
		audioContext=new AudioContext();
	}
	var source = audioContext.createBufferSource();

	audioContext.decodeAudioData(audioBlob,function(buffer){
		source.buffer = buffer;
		source.connect(audioContext.destination);
		source.start(0);
	});

//audioblobがない場合は合成音声で発話。recognitionTextはゲーム時に保存していた音声解析のテキスト。
}else{
	var speech=new SpeechSynthesisUtterance();
	speech.text=recognitionText;
	speech.lang = "ja-JP";
	speech.volume = 1;
	speechSynthesis.speak(speech);
}</pre><p></p>

<h2>最後に</h2>

<p>コトバツナギの主な仕組みは上記のようになっています。ゲーム本編だけでなく、ゲーム終了後にも参加者みんなで結果を振り返って楽しんでもらえるように作っています。音声解析がなかなかうまくいかないことも多いですが、思わぬ解析結果になることも含めて楽しんでもらえれば幸いです。<br>
よかったら遊んでみてください。</p>

<p>■コトバツナギ<br>
<a href="https://kotoba.tsukuenoue.com/" title="コトバツナギ" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">https://kotoba.tsukuenoue.com/</a></p>
]]></content:encoded>
		
		<series:name><![CDATA[HTML5 Japan Cup 特集]]></series:name>
	</item>
		<item>
		<title>WebRTC開発者向けライブラリ「PeerJS」はこうして作られた</title>
		<link>/yusuke-naka/3693/</link>
		<pubDate>Thu, 09 Jan 2014 02:00:26 +0000</pubDate>
		<dc:creator><![CDATA[仲 裕介]]></dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[PeerJS]]></category>
		<category><![CDATA[SkyWay]]></category>
		<category><![CDATA[WebRTC]]></category>
		<category><![CDATA[海外]]></category>

		<guid isPermaLink="false">/?p=3693</guid>
		<description><![CDATA[NTT Communications（以下、NTT Com）が提供するWebRTC開発用プラットフォーム SkyWayはPeerJSをベースに構成されています。この記事ではPeerJS開発者であるEric Zhang氏の...]]></description>
				<content:encoded><![CDATA[<p>NTT Communications（以下、NTT Com）が提供するWebRTC開発用プラットフォーム SkyWayはPeerJSをベースに構成されています。この記事ではPeerJS開発者であるEric Zhang氏の素顔に迫ります！</p>

<p><span id="more-3693"></span></p>

<h2>はじめに</h2>

<p>2013年11月19日から21日にアメリカで開催された<a href="http://www.webrtcworld.com/conference/west-13/default.aspx" title="webrtcworld" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">WebRTC Conference &amp; Expo</a>に合わせて、NTT ComのSkyWay開発担当者がアメリカを訪れ、PeerJS開発者の一人であるEric Zhang氏にインタビューを行いました。</p>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/01/7f8e62ed58e439286515234c8d8f655f2.jpg" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/01/7f8e62ed58e439286515234c8d8f655f2.jpg" alt="アレンとエリック" width="512" height="385" class="aligncenter size-full wp-image-4444" srcset="/wp-content/uploads/2014/01/7f8e62ed58e439286515234c8d8f655f2.jpg 512w, /wp-content/uploads/2014/01/7f8e62ed58e439286515234c8d8f655f2-300x225.jpg 300w, /wp-content/uploads/2014/01/7f8e62ed58e439286515234c8d8f655f2-207x155.jpg 207w" sizes="(max-width: 512px) 100vw, 512px" /></a></p>

<p style="text-align:center;"><small>（写真左：NTT com SkyWay開発チームの飯田アレン真人氏、写真右：PeerJS開発者のEric Zhang氏）</small></p>

<p><strong>──PeerJSとは？</strong></p>

<p>WebRTCを活用したアプリケーションを開発できるようにするためのJavaScriptライブラリ。<a href="http://peerjs.com/peerserver" title="PeerServer Cloud service" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PeerServer Cloud service</a>というWebRTCを実現するための仲介サーバ機能も提供している。</p>

<p><a href="http://peerjs.com/" title="PeerJS" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">http://peerjs.com/</a></p>

<p><strong>──SkyWayとは？</strong></p>

<p>Web開発者が高度な知識の習得や環境の整備をすることなく、WebRTCを活用したアプリケーションを開発できるように、PeerJS互換のJavaScriptライブラリ、仲介サーバ機能、WebAPI、日本語の開発ドキュメントを提供している。</p>

<p><a href="http://nttcom.github.io/skyway/" title="SkyWay" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">http://nttcom.github.io/skyway/</a></p>

<h2>学生時代に二人で開発をスタート</h2>

<p><strong>──どのような方が開発に携わられているのですか？</strong></p>

<p>私とMichelle Buの二人で開発しています。私は、過去にBinaryJSやNowJSなどを開発していました。特に、ネットワーク系の技術を簡単に使いやすくするためのライブラリ開発が得意です。MichelleはGoogleでインターンシップをしていたこともあり、JavaScriptを用いた開発経験が豊富なんです。</p>

<p><strong>──PeerJSはいつごろから開発を始めたのですか？</strong></p>

<p>私やMichelleがカリフォルニア大学バークレー校に在籍していた、2012年の12月にスタートしました。</p>

<h2>WebRTCが流行るのはわかっていた</h2>

<p><strong>──WebRTCという技術に触れてみて、最初はどう思いましたか？</strong></p>

<p>WebRTC DataChannelを利用してみると、多くの問題があることがわかりました。APIはブラウザごとに互換性がない、データのシリアライゼーションができない、そもそもシグナリングサーバが存在しないため利用するハードルが高いなど、とにかく使いにくい印象でした。しかし、ブラウザ上で動くWebアプリケーションはネイティブアプリケーションに比べて、ネットワーク技術を活用した開発を苦手としています。そのため、今後WebRTCは間違いなく流行る技術だと確信しました。</p>

<p><strong>──なぜPeerJSを開発しようと考えたのですか？</strong></p>

<p>私はもともと、JavaScriptの機能を簡単に利用できるようにするJavaScriptライブラリが好きでした。だからWebRTCの機能をみんなが簡単に使えるライブラリが、もっとあれば便利だと考え、開発をスタートしました。当初は開発者向けのチュートリアルも少なく、W3Cの仕様も毎週のように変わっていたこともあってかなり苦労しましたが、なんとか公開することができました。頑張ったかいあって、公開初日にGitHubにて700スターを頂きました。私が今までに開発したJavaScriptライブラリの中で、最も大規模なライブラリになりましたね。</p>

<h2>PeerJS開発の日々</h2>

<p><strong>──開発はどのように進めているのですか？</strong></p>

<p>私とMichelleは仕事をしながら、プライベートの時間でPeerJSの開発を進めてきました。現在も、毎日仕事から帰ってきたらメールと<a href="https://groups.google.com/forum/#!forum/peerjs" title="peerjs-googlegroup" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Peerjs &#8211; Google Group</a>を確認し、個別の質問への回答やバグ修正などを行っています。Chromeのコミットログも定期的に確認し、WebRTCに関する実装の進み具合も把握するようにしています。</p>

<h2>PeerJSに求めることは互換性と安定性</h2>

<p><strong>──今後PeerJSに新しい機能追加を行う予定はありますか？</strong></p>

<p>PeerJSへの機能追加は最小限にしたいと考えています。WebRTCの仕様自体が変化し続けているため、ブラウザのバージョンが上がるたびに使えなくなるという事態は避けなければなりません。WebRTC Working Groupの動向をウォッチし、仕様の変化に迅速に対応するとともに、高い安定性と互換性を維持していく方針です。もちろん、私達以外の開発者によるPeerJSへの機能追加は大歓迎です。そのためにMITライセンスで公開していますので、ぜひ、新しい機能をいろいろと追加してみてください。</p>

<p><strong>──最近はどのような開発をしているのでしょうか？</strong></p>

<p>PeerJSは2013年9月20日に、Version 0.2.xから0.3.xへ<a href="https://github.com/peers/peerjs/blob/master/changelog.md#version-030-beta-20-sept-2013" title="changelog" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">メジャーバージョンアップ</a>を行いました。主な変更は、WebRTCのMediaChannelへの対応です。2ヶ月ほどの開発で、同時にコア部分のリファクタリングも行いました。ループ処理を極力省き、信頼性や処理速度の向上などを目的にしたコードの最適化を行っています。処理速度向上のアプローチとしては、WebScoketsによる接続を行う前に、XHRにて通信することで、50msほど処理を速くすることができました。これは価値があることだと考えています。</p>

<p>今はバグ修正と処理速度の高速化に注力しています。例えば、Chrome 31からSCTP DataChannelがデフォルトで有効になりました。Chromeの実装ではデータを一時保管するバッファーサイズが1MBしかないため、データ転送速度が速いとデータが溢れてしまう可能性があります。そのため、これに対処するためのバッファーインターフェースを実装する必要があります。（※1）その他にもエラー処理や、ユーザのイベント処理を改善していきたいと考えています。</p>

<p><small>※１・・・この機能は<a href="https://github.com/peers/peerjs/blob/master/changelog.md#version-036-beta-3-dec-2013" title="peerjs-changelog" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Version 0.3.6 Beta (3 Dec 2013)</a>にて実装されました。</small></p>

<p><strong>──PeerJSのマネタイズはどう考えていますか？</strong></p>

<p>公開している<a href="http://peerjs.com/peerserver" title="PeerServer Cloud service" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PeerServer Cloud service</a>の運用には、費用はかかります。ですが、開発者の方に素早くサービスを開発してもらうことに重点を置いているため、私達でサーバを維持できるかぎり、有償化するつもりはありません。</p>

<h2>WebRTCは課題も多いけど、新しい可能性を秘めた技術</h2>

<p><a href="https://html5experts.jp/wp-content/uploads/2014/01/be8bdbdab642932ea12f5e7795c4fa781.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/01/be8bdbdab642932ea12f5e7795c4fa781.png" alt="エリック" width="383" height="421" class="alignright size-full wp-image-4441" srcset="/wp-content/uploads/2014/01/be8bdbdab642932ea12f5e7795c4fa781.png 383w, /wp-content/uploads/2014/01/be8bdbdab642932ea12f5e7795c4fa781-272x300.png 272w, /wp-content/uploads/2014/01/be8bdbdab642932ea12f5e7795c4fa781-188x207.png 188w" sizes="(max-width: 383px) 100vw, 383px" /></a><strong>──WebRTCに関して課題だと感じていることはありますか？</strong></p>

<p>WebRTCはPeer-to-Peerを前提にしているので、グループビデオチャットを簡単に実装することができません。サーバ側でミキシングを行い、複数人でチャットなどができる商用サービスはいくつか存在します。しかし、オープンソースで公開されているものはありません。今後はnpm installで簡単にインストールできる、オープンソースのサーバプロダクトが出てくることを願っています。</p>

<p><strong>──WebRTCを活用した新しいユースケースはありますか？</strong></p>

<p><a href="https://peercdn.com/" title="PeerCDN" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">PeerCDN</a>というサービスは面白いと思います。これは、Webサイト上の画像や音声、動画などのコンテンツを、その時に同じようにWebサイトを閲覧しているユーザ同士でシェアしあうサービスです。WebRTCの機能を使い、Peer-to-Peerの片方がCDNの役割を果たし、コンテンツを他方に配信します。サーバからダウンロードするよりも高速にコンテンツが取得できるようになれば、多くの人から注目されるでしょう。</p>

<p>WebRTCは新しくてとても魅力的なAPIです。今後の可能性に期待しています。</p>

<h2>終わりに</h2>

<p>今回はPeerJSの開発者であるEric Zhang氏へのインタビューをお送りしました。残念ながら、Michelle Bu氏には時間が合わずお話を伺うことができませんでしたが、Eric氏は一人のエンジニアとしてすごくバイタリティにあふれている方でした。また、HTML5とJavaScriptでつくるエコシステムにすごい可能性を感じており、ちょっと大げさかもしれませんが、同時にWeb技術への愛が感じられました。今後の活躍を大いに期待したいと思います。</p>

<p>NTT ComのSkyWay開発チームは、今後もSkyWayをはじめとするWebRTCに関する情報発信を行っていきますので、ご期待ください。</p>

<p><small>ここだけの話、ErichとMichelleはお付き合いしているそうです。二人がこの先もうまくいくといいですね。</small></p>

<p><style><!--
.exp-comment {   border-top: 1px solid lightgray; } .exp-thumbnail { } .exp-info {   font-size: 1.1em !important;   margin-bottom: 0 !important; } .exp-comment-pubdate {   font-size: .8em !important;   margin-bottom: 4px !important; } .exp-comment-main {   border: 1px solid lightgray;   border-radius: 8px;   padding: 1em;   min-height: 70px;   margin-bottom: 16px; } .exp-thumbnail {   width: 70px;   float: left; } .exp-comment-body {   margin-left: 80px;  } .editor-comment {   clear: left; } .exp-question {   font-weight: bold;   margin-bottom: 8px; } .post-detail-contents blockquote { background-image: none; }
--></style><article class="exp-comment"></p>

<div class="exp-comment-main">
<div class="exp-thumbnail"><a href="https://html5experts.jp/wp-content/uploads/2014/01/4b543d265860b1af3bffec4cf3b91272.png" data-wpel-link="external" target="_blank" rel="follow external noopener noreferrer"><img src="/wp-content/uploads/2014/01/4b543d265860b1af3bffec4cf3b91272.png" alt="エリック顔_small" width="47" height="71" class="aligncenter size-full wp-image-4491" /></a></div>
<blockquote class="exp-comment-body">[Eric Zhang/エリック・ザング]

中国生まれで2000年からアメリカに在住。2009年にカリフォルニア大学バークレー校に入学。在学中にFlotype incにて<a href="https://github.com/Flotype" title="Flotype - Github" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">NowJS</a>の開発に携わる。2012年には同じく学生だったMichelle Buと共にPeerJSの開発を始める。現在は<a href="https://lever.co/" title="Lever inc." target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">Lever inc</a>の開発に携わりつつ、PeerJSの開発も継続して行っている。JavaScriptライブラリの開発が得意で<a href="http://binaryjs.com/" title="binaryjs" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">BinaryJS</a>の開発なども行っている。<a href="http://ericzhang.com/" title="ericzhang.com" target="_blank" data-wpel-link="external" rel="follow external noopener noreferrer">http://ericzhang.com/</a>
</blockquote>
</div>

<p></article></p>
]]></content:encoded>
			</item>
	</channel>
</rss>
