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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
|
---
title: RTCPeerConnection
slug: Web/API/RTCPeerConnection
tags:
- API
- Audio
- Communication
- Interface
- Media
- NeedsUpdate
- Networking
- RTCPeerConnection
- Reference
- Telecom
- Video
- WebRTC
- WebRTC API
translation_of: Web/API/RTCPeerConnection
---
<p>{{APIRef('WebRTC')}}</p>
<p><span class="seoSummary"><strong><code>RTCPeerConnection</code></strong> インターフェイスはローカルコンピューターとリモートピア間の WebRTC コネクションを表現します。このインターフェイスはリモートピアへ接続や、その接続の保守や監視するメソッド、さらに、不要になった接続を閉じるメソッドを提供します。</span></p>
<p>{{InheritanceDiagram}}</p>
<div>{{InterfaceOverview("WebRTC")}}</div>
<h3 id="Obsolete_method" name="Obsolete_method">廃止されたメソッド</h3>
<p>以下のメソッドは廃止されており、すべての主要なブラウザーで未実装です。</p>
<dl>
<dt>{{domxref("RTCPeerConnection.createDTMFSender()")}} {{obsolete_inline}}</dt>
<dd>特定の {{domxref("MediaStreamTrack")}} と関連付けられた新たな {{domxref("RTCDTMFSender")}} を生成します。これにより、その接続において {{Glossary("DTMF")}} 音(電話のトーン信号、プッシュ音)を送れるようになるでしょう。</dd>
</dl>
<h2 id="Events" name="Events">イベント</h2>
<p>これらのイベントを待ち受けするには、 {{domxref("EventTarget.addEventListener", "addEventListener()")}} を使用するか、イベントリスナーをこのインターフェイスの <code>on<em>イベント名</em></code> プロパティに代入するかしてください。</p>
<dl>
<dt>{{domxref("RTCPeerConnection.connectionstatechange_event", "connectionstatechange")}}</dt>
<dd><code>RTCPeerConnection</code> の全体的な接続ステータスが変更されると、 <code>RTCPeerConnection</code> オブジェクトに送信されます。<br>
{{domxref("RTCPeerConnection.onconnectionstatechange", "onconnectionstatechange")}} イベントハンドラプロパティからも使用できます。</dd>
<dt>{{domxref("RTCPeerConnection.datachannel_event", "datachannel")}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> object when the remote peer adds an {{domxref("RTCDataChannel")}} to the connection.<br>
Also available through the {{domxref("RTCPeerConnection.ondatachannel", "ondatachannel")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.icecandidate_event", "icecandidate")}}</dt>
<dd>Sent to the peer connection to request that the specified candidate be transmitted to the remote peer.<br>
Also available through the {{domxref("RTCPeerConnection.onicecandidate", "onicecandidate")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.icecandidateerror_event", "icecandidateerror")}}</dt>
<dd>An error of type {{domxref("RTCPeerConnectionIceErrorEvent")}} which is sent to the connection if an error occurred during ICE candidate gathering. The event's properties describe the error.<br>
Also available through the {{domxref("RTCPeerConnection.onicecandidateerror", "onicecandidateerror")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.iceconnectionstatechange_event", "iceconnectionstatechange")}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> when the state of the ICE connection changes, such as when it disconnects.<br>
Also available using the {{domxref("RTCPeerConnection.oniceconnectionstatechange", "oniceconnectionstatechange")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.icegatheringstatechange_event", "icegatheringstatechange")}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> when the ICE layer's gathering state, reflected by {{domxref("RTCPeerConnection.iceGatheringState", "iceGatheringState")}}, changes. This indicates whether ICE negotiation has not yet begun (<code>new</code>), has begun gathering candidates (<code>gathering</code>), or has completed (<code>complete</code>).<br>
Also available using the {{domxref("RTCPeerConnection.onicegatheringstatechange", "onicegatheringstatechange")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.isolationchange_event", "isolationchange")}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> when the {{domxref("MediaStreamTrack.isolated", "isolated")}} property on one of the {{domxref("MediaStreamTrack")}} objects associated with the connection changes value. A track is {{domxref("MediaStreamTrack.isolated", "isolated")}} if its content cannot be accessed by the owning document due to lack of authentication or if the track comes from a cross-origin source.<br>
Also available through the {{domxref("RTCPeerConnection.onisolationchange", "onisolationchange")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.negotiationneeded_event", "negotiationneeded")}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> when negotiation or renegotiation of the ICE connection needs to be performed; this can happen both when first opening a connection as well as when it's neccessary to adapt to changing network conditions. The receiver should respond by creating an offer and sending it to the other peer.<br>
Also available as the {{domxref("RTCPeerConnection.onnegotiationneeded", "onnegotiationneeded")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.signalingstatechange_event", "signalingstatechange")}}</dt>
<dd>The <code>signalingstatechange</code> event is sent to the <code>RTCPeerConnection</code> when the connection's ICE signaling state changes.<br>
Also available through the {{domxref("RTCPeerConnection.onsignalingstatechange", "onsignalingstatechange")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.statsended_event", "statsended")}}</dt>
<dd>The <code>statsended</code> event is sent when a statistics object being monitored is deleted. The {{domxref("RTCStatsEvent")}} includes the final report on the deleted object (or objects, if multiple objects have been deleted since the last report was delivered). A statistics object is deleted, for example, when the connection is closed and deleted.<br>
Available as the {{domxref("RTCPeerConnection.onstatsended", "onstatsended")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.track_event", "track")}}</dt>
<dd>The <code>track</code> event is sent after a new track has been added to one of the {{domxref("RTCRtpReceiver")}} instances which comprise the connection.<br>
Available as the {{domxref("RTCPeerConnection.ontrack", "ontrack")}} event handler property.</dd>
</dl>
<h3 id="Obsolete_events" name="Obsolete_events">廃止されたイベント</h3>
<dl>
<dt>{{domxref("RTCPeerConnection.addstream_event", "addstream")}} {{obsolete_inline}}</dt>
<dd>Sent when a new {{domxref("MediaStream")}} has been added to the connection. Instead of watching for this obsolete event, you should watch each for {{domxref("RTCPeerConnection.track_event", "track")}} events; one is sent for each {{domxref("MediaStreamTrack")}} added to the connection.<br>
Available as the {{domxref("RTCPeerConnection.onaddstream", "onaddstream")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.identityresult_event", "identityresult")}} {{obsolete_inline}}</dt>
<dd>In old versions of the WebRTC specification, this event was used to indicate that an identity assertion is available. Now, you should instead wait for a the promise returned by {{domxref("RTCPeerConnection.peerIdentity", "peerIdentity")}} to resolve with an identity.<br>
Also available using the {{domxref("RTCPeerConnection.onidentityresult", "onidentityresult")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.idpassertionerror_event", "idpassertionerror")}} {{obsolete_inline}}</dt>
<dd>In old versions of the WebRTC specification, this event was used to indicate that an error occurred while attempting to generate an identity assertion. Now, you should instead wait for a the promise returned by {{domxref("RTCPeerConnection.peerIdentity", "peerIdentity")}} to be rejected with an error.<br>
Also available as the {{domxref("RTCPeerConnection.onidpassertionerror", "onidpinsertionerror")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.idpvalidationerror_event", "idpvalidationerror")}} {{obsolete_inline}}</dt>
<dd>In old versions of the WebRTC specification, this event was used to indicate that an error occurred while attempting to validate an identity assertion. Now, you should instead wait for a the promise returned by {{domxref("RTCPeerConnection.peerIdentity", "peerIdentity")}} to be rejected with an error.<br>
Also available using the {{domxref("RTCPeerConnection.onpeeridentity", "onpeerdentity")}} event handler property.</dd>
<dt>{{domxref("RTCPeerConnection.peeridentity_event", "peeridentity")}} {{obsolete_inline}}</dt>
<dd>In old versions of the WebRTC specification, this event was used to deliver a received identity. Now, you should instead wait for a the promise returned by {{domxref("RTCPeerConnection.peerIdentity", "peerIdentity")}} to resolve with an identity.</dd>
<dt>{{domxref("RTCPeerConnection.removestream_event", "removestream")}} {{obsolete_inline}}</dt>
<dd>Sent to the <code>RTCPeerConnection</code> when a {{domxref("MediaStream")}} is removed from the connection. Instead of watching for this obsolete event, you should watch each stream for {{domxref("MediaStream.removetrack_event", "removetrack")}} events on each stream within the <code>RTCPeerConnection</code>.<br>
Also available as the {{domxref("RTCPeerConnection.onremovestream", "onaddstream")}} event handler property.</dd>
</dl>
<h2 id="Constants" name="Constants">定数</h2>
<h3 id="RTCBundlePolicy_列挙型">RTCBundlePolicy 列挙型</h3>
<p>この <code>RTCBundlePolicy</code> 列挙型は、リモートピアが、単一の転送リンクにおいて複数のメディアストリームをまとめるための <a href="https://webrtcstandards.info/sdp-bundle/">SDP BUNDLE standard</a> と互換していない場合に、ICEの候補を収集するために特定のポリシーを要求する時に使用される文字列定数を定義します。</p>
<div class="note">
<p><strong>Note:</strong> In technical terms, a BUNDLE lets all media flow between two peers flow across a single <strong>5-tuple</strong>; that is, from the same IP and port on one peer to the same IP and port on the other peer, using the same transport protocol.</p>
</div>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"balanced"</code></td>
<td>On BUNDLE-aware connections, the ICE agent should gather candidates for all of the media types in use (audio, video, and data). Otherwise, the ICE agent should only negotiate one audio and video track on separate transports.</td>
</tr>
<tr>
<td><code>"max-compat"</code></td>
<td>The ICE agent should gather candidates for each track, using separate transports to negotiate all media tracks for connections which aren't BUNDLE-compatible.</td>
</tr>
<tr>
<td><code>"max-bundle"</code></td>
<td>The ICE agent should gather candidates for just one track. If the connection isn't BUNDLE-compatible, then the ICE agent should negotiate just one media track.</td>
</tr>
</tbody>
</table>
<h3 id="RTCIceConnectionState_列挙型">RTCIceConnectionState 列挙型</h3>
<p>The <code>RTCIceConnectionState</code> enum defines the string constants used to describe the current state of the ICE agent and its connection to the ICE server (that is, the {{Glossary("STUN")}} or {{Glossary("TURN")}} server).</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"new"</code></td>
<td>The ICE agent is gathering addresses or is waiting to be given remote candidates through calls to {{domxref("RTCPeerConnection.addIceCandidate()")}} (or both).</td>
</tr>
<tr>
<td><code>"checking"</code></td>
<td>The ICE agent has been given one or more remote candidates and is checking pairs of local and remote candidates against one another to try to find a compatible match, but has not yet found a pair which will allow the peer connection to be made. It's possible that gathering of candidates is also still underway.</td>
</tr>
<tr>
<td><code>"connected"</code></td>
<td>A usable pairing of local and remote candidates has been found for all components of the connection, and the connection has been established. It's possible that gathering is still underway, and it's also possible that the ICE agent is still checking candidates against one another looking for a better connection to use.</td>
</tr>
<tr>
<td><code>"completed"</code></td>
<td>The ICE agent has finished gathering candidates, has checked all pairs against one another, and has found a connection for all components.</td>
</tr>
<tr>
<td><code>"failed"</code></td>
<td>The ICE candidate has checked all candidates pairs against one another and has failed to find compatible matches for all components of the connection. It is, however, possible that the ICE agent did find compatible connections for some components.</td>
</tr>
<tr>
<td><code>"disconnected"</code></td>
<td>Checks to ensure that components are still connected failed for at least one component of the {{domxref("RTCPeerConnection")}}. This is a less stringent test than <code>"failed"</code> and may trigger intermittently and resolve just as spontaneously on less reliable networks, or during temporary disconnections. When the problem resolves, the connection may return to the <code>"connected"</code> state.</td>
</tr>
<tr>
<td><code>"closed"</code></td>
<td>The ICE agent for this {{domxref("RTCPeerConnection")}} has shut down and is no longer handling requests.</td>
</tr>
</tbody>
</table>
<h3 id="RTCIceGatheringState_列挙型">RTCIceGatheringState 列挙型</h3>
<p>The <code>RTCIceGatheringState</code> enum defines string constants which reflect the current status of ICE gathering, as returned using the {{domxref("RTCPeerConnection.iceGatheringState")}} property. You can detect when this value changes by watching for an event of type {{event("icegatheringstatechange")}}.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"new"</code></td>
<td>The peer connection was just created and hasn't done any networking yet.</td>
</tr>
<tr>
<td><code>"gathering"</code></td>
<td>The ICE agent is in the process of gathering candidates for the connection.</td>
</tr>
<tr>
<td><code>"complete"</code></td>
<td>The ICE agent has finished gathering candidates. If something happens that requires collecting new candidates, such as a new interface being added or the addition of a new ICE server, the state will revert to "gathering" to gather those candidates.</td>
</tr>
</tbody>
</table>
<h3 id="RTCIceTransportPolicy_列挙型">RTCIceTransportPolicy 列挙型</h3>
<p>The <code>RTCIceTransportPolicy</code> enum defines string constants which can be used to limit the transport policies of the ICE candidates to be considered during the connection process.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"all"</code></td>
<td>All ICE candidates will be considered.</td>
</tr>
<tr>
<td><code>"public" </code>{{obsolete_inline}}</td>
<td>Only ICE candidates with public IP addresses will be considered. <em>Removed from the specification's May 13, 2016 working draft.</em></td>
</tr>
<tr>
<td><code>"relay"</code></td>
<td>Only ICE candidates whose IP addresses are being relayed, such as those being passed through a TURN server, will be considered.</td>
</tr>
</tbody>
</table>
<h3 id="RTCPeerConnectionState_列挙型">RTCPeerConnectionState 列挙型</h3>
<p>The <code>RTCPeerConnectionState</code> enum defines string constants which describe states in which the <code>RTCPeerConnection</code> may be. These values are returned by the {{domxref("RTCPeerConnection.connectionState", "connectionState")}} property. This state essentially represents the aggregate state of all ICE transports (which are of type {{domxref("RTCIceTransport")}} or {{domxref("RTCDtlsTransport")}}) being used by the connection.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"new"</code></td>
<td>At least one of the connection's ICE transports ({{domxref("RTCIceTransport")}}s or {{domxref("RTCDtlsTransport")}}s) are in the <code>"new"</code> state, and none of them are in one of the following states: <code>"connecting"</code>, <code>"checking"</code>, <code>"failed"</code>, or <code>"disconnected"</code>, <em>or</em> all of the connection's transports are in the <code>"closed"</code> state.</td>
</tr>
<tr>
<td><code>"connecting"</code></td>
<td>One or more of the ICE transports are currently in the process of establishing a connection; that is, their <code>RTCIceConnectionState</code> is either <code>"checking"</code> or <code>"connected"</code>, and no transports are in the <code>"failed"</code> state. <strong><<< Make this a link once I know where that will be documented</strong></td>
</tr>
<tr>
<td><code>"connected"</code></td>
<td>Every ICE transport used by the connection is either in use (state <code>"connected"</code> or <code>"completed"</code>) or is closed (state <code>"closed"</code>); in addition, at least one transport is either <code>"connected"</code> or <code>"completed"</code>.</td>
</tr>
<tr>
<td><code>"disconnected"</code></td>
<td>At least one of the ICE transports for the connection is in the <code>"disconnected"</code> state and none of the other transports are in the state <code>"failed"</code>, <code>"connecting"</code>, or <code>"checking"</code>.</td>
</tr>
<tr>
<td><code>"failed"</code></td>
<td>One or more of the ICE transports on the connection is in the <code>"failed"</code> state.</td>
</tr>
<tr>
<td><code>"closed"</code></td>
<td>
<p>The <code>RTCPeerConnection</code> is closed.</p>
<p>This value was in the <a href="#RTCSignalingState_enum"><code>RTCSignalingState</code> enum</a> (and therefore found by reading the value of the {{domxref("RTCPeerConnection.signalingState", "signalingState")}}) property until the May 13, 2016 draft of the specification.</p>
</td>
</tr>
</tbody>
</table>
<h3 id="RTCRtcpMuxPolicy_列挙型">RTCRtcpMuxPolicy 列挙型</h3>
<p>The <code>RTCRtcpMuxPolicy</code> enum defines string constants which specify what ICE candidates are gathered to support non-multiplexed RTCP. <strong><<<add a link to info about multiplexed RTCP.</strong></p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"negotiate"</code></td>
<td>Instructs the ICE agent to gather both {{Glossary("RTP")}} and {{Glossary("RTCP")}} candidates. If the remote peer can multiplex RTCP, then RTCP candidates are multiplexed atop the corresponding RTP candidates. Otherwise, both the RTP and RTCP candidates are returned, separately.</td>
</tr>
<tr>
<td><code>"require"</code></td>
<td>Tells the ICE agent to gather ICE candidates for only RTP, and to multiplex RTCP atop them. If the remote peer doesn't support RTCP multiplexing, then session negotiation fails.</td>
</tr>
</tbody>
</table>
<h3 id="RTCSignalingState_列挙型">RTCSignalingState 列挙型</h3>
<p>The <code>RTCSignalingState</code> enum specifies the possible values of {{domxref("RTCPeerConnection.signalingState")}}, which indicates where in the process of signaling the exchange of offer and answer the connection currently is.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="col">Constant</th>
<th scope="col">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>"stable"</code></td>
<td>There is no ongoing exchange of offer and answer underway. This may mean that the {{domxref("RTCPeerConnection")}} object is new, in which case both the {{domxref("RTCPeerConnection.localDescription", "localDescription")}} and {{domxref("RTCPeerConnection.remoteDescription", "remoteDescription")}} are <code>null</code>; it may also mean that negotiation is complete and a connection has been established.</td>
</tr>
<tr>
<td><code>"have-local-offer"</code></td>
<td>The local peer has called {{domxref("RTCPeerConnection.setLocalDescription()")}}, passing in SDP representing an offer (usually created by calling {{domxref("RTCPeerConnection.createOffer()")}}), and the offer has been applied successfully.</td>
</tr>
<tr>
<td><code>"have-remote-offer"</code></td>
<td>The remote peer has created an offer and used the signaling server to deliver it to the local peer, which has set the offer as the remote description by calling {{domxref("RTCPeerConnection.setRemoteDescription()")}}.</td>
</tr>
<tr>
<td><code>"have-local-pranswer"</code></td>
<td>The offer sent by the remote peer has been applied and an answer has been created (usually by calling {{domxref("RTCPeerConnection.createAnswer()")}}) and applied by calling {{domxref("RTCPeerConnection.setLocalDescription()")}}. This provisional answer describes the supported media formats and so forth, but may not have a complete set of ICE candidates included. Further candidates will be delivered separately later.</td>
</tr>
<tr>
<td><code>"have-remote-pranswer"</code></td>
<td>A provisional answer has been received and successfully applied in response to an offer previously sent and established by calling <code>setLocalDescription()</code>.</td>
</tr>
<tr>
<td><code>"closed"</code> {{obsolete_inline}}</td>
<td>
<p>The connection is closed.</p>
<div class="note">
<p><strong>Note:</strong> This value moved into the <a href="#RTCPeerConnectionState_enum"><code>RTCPeerConnectionState</code> enum</a> in the May 13, 2016 draft of the specification, as it reflects the state of the <code>RTCPeerConnection</code>, not the signaling connection. You now detect a closed connection by checking for {{domxref("RTCPeerConnection.connectionState", "connectionState")}} to be <code>"closed"</code> instead.</p>
</div>
</td>
</tr>
</tbody>
</table>
<h2 id="Specifications" name="Specifications">仕様書</h2>
<table class="standard-table">
<thead>
<tr>
<th scope="col">仕様書</th>
<th scope="col">状態</th>
<th scope="col">備考</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{SpecName('WebRTC 1.0', '#interface-definition', 'RTCPeerConnection')}}</td>
<td>{{Spec2('WebRTC 1.0')}}</td>
<td>初回定義</td>
</tr>
</tbody>
</table>
<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2>
<p>{{Compat("api.RTCPeerConnection")}}</p>
<h2 id="See_also" name="See_also">関連情報</h2>
<ul>
<li><a href="https://github.com/jesup/nightly-gupshup/blob/master/static/js/chat.js">https://github.com/jesup/nightly-gupshup/blob/master/static/js/chat.js</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/webrtc/basics/#toc-simple">http://www.html5rocks.com/en/tutorials/webrtc/basics/#toc-simple</a></li>
<li><a href="https://github.com/chrisjohndigital/TutorRoom">TutorRoom</a>: Node.js HTML5 video capture, peer-to-peer video and filesharing application (<a href="https://github.com/chrisjohndigital/TutorRoom">source on GitHub</a>)</li>
</ul>
|