Skip to content

Commit 279e0ec

Browse files
committed
Merge pull request webrtc#744 from samdutton/gh-pages
New demo: peer connection to Web Audio
2 parents a1708d5 + df30724 commit 279e0ec

File tree

6 files changed

+437
-0
lines changed

6 files changed

+437
-0
lines changed

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ Head over to [test/README.md](https://github.com/webrtc/samples/blob/gh-pages/te
7474

7575
[Web Audio output as input to peer connection](https://webrtc.github.io/samples/src/content/peerconnection/webaudio-input/)
7676

77+
[Peer connection as input to Web Audio](https://webrtc.github.io/samples/src/content/peerconnection/webaudio-output/)
78+
7779
### RTCDataChannel ###
7880

7981
[Transmit text](https://webrtc.github.io/samples/src/content/datachannel/basic/)

index.html

+2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ <h3 id="peerconnection">RTCPeerConnection</h3>
128128

129129
<p><a href="src/content/peerconnection/webaudio-input/">Web Audio output as input to peer connection</a></p>
130130

131+
<p><a href="src/content/peerconnection/webaudio-output/">Peer connection as input to Web Audio</a></p>
132+
131133
<h3 id="datachannel">RTCDataChannel</h3>
132134

133135
<p><a href="src/content/datachannel/basic/">Transmit text</a></p>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3+
*
4+
* Use of this source code is governed by a BSD-style license
5+
* that can be found in the LICENSE file in the root of the source
6+
* tree.
7+
*/
8+
9+
button {
10+
margin: 0 20px 0 0;
11+
width: 83px;
12+
}
13+
14+
button#hangupButton {
15+
margin: 0;
16+
}
17+
18+
canvas {
19+
background-color: #666;
20+
height: 231px;
21+
vertical-align: top;
22+
width: calc(50% - 12px);
23+
}
24+
25+
video {
26+
height: 231px;
27+
margin: 0 20px 20px 0;
28+
width: calc(50% - 12px);
29+
}
30+
31+
video#remoteVideo {
32+
display: none;
33+
}
34+
35+
@media screen and (max-width: 400px) {
36+
button {
37+
margin: 0 11px 10px 0;
38+
width: 83px;
39+
}
40+
canvas {
41+
width: calc(50% - 7px);
42+
}
43+
video {
44+
margin: 0 10px 20px 0;
45+
width: calc(50% - 7px);
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<!DOCTYPE html>
2+
<!--
3+
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
4+
*
5+
* Use of this source code is governed by a BSD-style license
6+
* that can be found in the LICENSE file in the root of the source
7+
* tree.
8+
-->
9+
<html>
10+
<head>
11+
12+
<meta charset="utf-8">
13+
<meta name="description" content="WebRTC code samples">
14+
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1">
15+
<meta itemprop="description" content="Client-side WebRTC code samples">
16+
<meta itemprop="image" content="../../../images/webrtc-icon-192x192.png">
17+
<meta itemprop="name" content="WebRTC code samples">
18+
<meta name="mobile-web-app-capable" content="yes">
19+
<meta id="theme-color" name="theme-color" content="#ffffff">
20+
21+
<base target="_blank">
22+
23+
<title>Peer connection as input to Web Audio</title>
24+
25+
<link rel="icon" sizes="192x192" href="../../../images/webrtc-icon-192x192.png">
26+
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
27+
<link rel="stylesheet" href="../../../css/main.css" />
28+
<link rel="stylesheet" href="css/main.css" />
29+
30+
</head>
31+
32+
<body>
33+
34+
<div id="container">
35+
36+
<h1><a href="//webrtc.github.io/samples/" title="WebRTC samples homepage">WebRTC samples</a> <span>Peer connection as input to Web Audio</span></h1>
37+
38+
<video id="localVideo" autoplay muted></video>
39+
<video id="remoteVideo" autoplay muted></video>
40+
41+
<canvas></canvas>
42+
43+
<div>
44+
<button id="startButton">Start</button>
45+
<button id="callButton">Call</button>
46+
<button id="hangupButton">Hang Up</button>
47+
</div>
48+
49+
<p>View the console to see logging. The <code>MediaStream</code> object <code>localStream</code>, and the <code>RTCPeerConnection</code> objects <code>localPeerConnection</code> and <code>remotePeerConnection</code> are in global scope, so you can inspect them in the console as well.</p>
50+
51+
<p>For more information about RTCPeerConnection, see <a href="http://www.html5rocks.com/en/tutorials/webrtc/basics/" title="HTML5 Rocks article about WebRTC by Sam Dutton">Getting Started With WebRTC</a>.</p>
52+
53+
54+
<a href="https://github.com/webrtc/samples/tree/gh-pages/src/content/peerconnection/pc1" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>
55+
56+
</div>
57+
58+
<script src="../../../js/adapter.js"></script>
59+
<script src="../../../js/common.js"></script>
60+
<script src="js/third_party/streamvisualizer.js"></script>
61+
<script src="js/main.js"></script>
62+
63+
<script src="../../../js/lib/ga.js"></script>
64+
</body>
65+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3+
*
4+
* Use of this source code is governed by a BSD-style license
5+
* that can be found in the LICENSE file in the root of the source
6+
* tree.
7+
*/
8+
9+
/* globals StreamVisualizer */
10+
11+
'use strict';
12+
13+
var startButton = document.getElementById('startButton');
14+
var callButton = document.getElementById('callButton');
15+
var hangupButton = document.getElementById('hangupButton');
16+
callButton.disabled = true;
17+
hangupButton.disabled = true;
18+
startButton.onclick = start;
19+
callButton.onclick = call;
20+
hangupButton.onclick = hangup;
21+
22+
var canvas = document.querySelector('canvas');
23+
24+
var startTime;
25+
var localVideo = document.getElementById('localVideo');
26+
var remoteVideo = document.getElementById('remoteVideo');
27+
28+
localVideo.addEventListener('loadedmetadata', function() {
29+
trace('Local video videoWidth: ' + this.videoWidth +
30+
'px, videoHeight: ' + this.videoHeight + 'px');
31+
});
32+
33+
remoteVideo.addEventListener('loadedmetadata', function() {
34+
trace('Remote video videoWidth: ' + this.videoWidth +
35+
'px, videoHeight: ' + this.videoHeight + 'px');
36+
});
37+
38+
remoteVideo.addEventListener('resize', function() {
39+
trace('Remote video size changed to ' +
40+
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
41+
// We'll use the first onsize callback as an indication that video has started
42+
// playing out.
43+
if (startTime) {
44+
var elapsedTime = window.performance.now() - startTime;
45+
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
46+
startTime = null;
47+
}
48+
});
49+
50+
var localStream;
51+
var pc1;
52+
var pc2;
53+
var offerOptions = {
54+
offerToReceiveAudio: 1,
55+
offerToReceiveVideo: 1
56+
};
57+
58+
function getName(pc) {
59+
return (pc === pc1) ? 'pc1' : 'pc2';
60+
}
61+
62+
function getOtherPc(pc) {
63+
return (pc === pc1) ? pc2 : pc1;
64+
}
65+
66+
function gotStream(stream) {
67+
trace('Received local stream');
68+
localVideo.srcObject = stream;
69+
localStream = stream;
70+
callButton.disabled = false;
71+
}
72+
73+
function start() {
74+
trace('Requesting local stream');
75+
startButton.disabled = true;
76+
navigator.mediaDevices.getUserMedia({
77+
audio: true,
78+
video: true
79+
})
80+
.then(gotStream)
81+
.catch(function(e) {
82+
alert('getUserMedia() error: ' + e.name);
83+
});
84+
}
85+
86+
function call() {
87+
callButton.disabled = true;
88+
hangupButton.disabled = false;
89+
trace('Starting call');
90+
startTime = window.performance.now();
91+
var videoTracks = localStream.getVideoTracks();
92+
var audioTracks = localStream.getAudioTracks();
93+
if (videoTracks.length > 0) {
94+
trace('Using video device: ' + videoTracks[0].label);
95+
}
96+
if (audioTracks.length > 0) {
97+
trace('Using audio device: ' + audioTracks[0].label);
98+
}
99+
var servers = null;
100+
pc1 = new RTCPeerConnection(servers);
101+
trace('Created local peer connection object pc1');
102+
pc1.onicecandidate = function(e) {
103+
onIceCandidate(pc1, e);
104+
};
105+
pc2 = new RTCPeerConnection(servers);
106+
trace('Created remote peer connection object pc2');
107+
pc2.onicecandidate = function(e) {
108+
onIceCandidate(pc2, e);
109+
};
110+
pc1.oniceconnectionstatechange = function(e) {
111+
onIceStateChange(pc1, e);
112+
};
113+
pc2.oniceconnectionstatechange = function(e) {
114+
onIceStateChange(pc2, e);
115+
};
116+
pc2.onaddstream = gotRemoteStream;
117+
118+
pc1.addStream(localStream);
119+
trace('Added local stream to pc1');
120+
121+
trace('pc1 createOffer start');
122+
pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
123+
offerOptions);
124+
}
125+
126+
function onCreateSessionDescriptionError(error) {
127+
trace('Failed to create session description: ' + error.toString());
128+
}
129+
130+
function onCreateOfferSuccess(desc) {
131+
trace('Offer from pc1\n' + desc.sdp);
132+
trace('pc1 setLocalDescription start');
133+
pc1.setLocalDescription(desc, function() {
134+
onSetLocalSuccess(pc1);
135+
}, onSetSessionDescriptionError);
136+
trace('pc2 setRemoteDescription start');
137+
pc2.setRemoteDescription(desc, function() {
138+
onSetRemoteSuccess(pc2);
139+
}, onSetSessionDescriptionError);
140+
trace('pc2 createAnswer start');
141+
// Since the 'remote' side has no media stream we need
142+
// to pass in the right constraints in order for it to
143+
// accept the incoming offer of audio and video.
144+
pc2.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
145+
}
146+
147+
function onSetLocalSuccess(pc) {
148+
trace(getName(pc) + ' setLocalDescription complete');
149+
}
150+
151+
function onSetRemoteSuccess(pc) {
152+
trace(getName(pc) + ' setRemoteDescription complete');
153+
}
154+
155+
function onSetSessionDescriptionError(error) {
156+
trace('Failed to set session description: ' + error.toString());
157+
}
158+
159+
function gotRemoteStream(e) {
160+
remoteVideo.srcObject = e.stream;
161+
trace('pc2 received remote stream');
162+
var streamVisualizer = new StreamVisualizer(e.stream, canvas);
163+
streamVisualizer.start();
164+
}
165+
166+
167+
function onCreateAnswerSuccess(desc) {
168+
trace('Answer from pc2:\n' + desc.sdp);
169+
trace('pc2 setLocalDescription start');
170+
pc2.setLocalDescription(desc, function() {
171+
onSetLocalSuccess(pc2);
172+
}, onSetSessionDescriptionError);
173+
trace('pc1 setRemoteDescription start');
174+
pc1.setRemoteDescription(desc, function() {
175+
onSetRemoteSuccess(pc1);
176+
}, onSetSessionDescriptionError);
177+
}
178+
179+
function onIceCandidate(pc, event) {
180+
if (event.candidate) {
181+
getOtherPc(pc).addIceCandidate(new RTCIceCandidate(event.candidate),
182+
function() {
183+
onAddIceCandidateSuccess(pc);
184+
},
185+
function(err) {
186+
onAddIceCandidateError(pc, err);
187+
}
188+
);
189+
trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate);
190+
}
191+
}
192+
193+
function onAddIceCandidateSuccess(pc) {
194+
trace(getName(pc) + ' addIceCandidate success');
195+
}
196+
197+
function onAddIceCandidateError(pc, error) {
198+
trace(getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
199+
}
200+
201+
function onIceStateChange(pc, event) {
202+
if (pc) {
203+
trace(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
204+
console.log('ICE state change event: ', event);
205+
}
206+
}
207+
208+
function hangup() {
209+
trace('Ending call');
210+
pc1.close();
211+
pc2.close();
212+
pc1 = null;
213+
pc2 = null;
214+
hangupButton.disabled = true;
215+
callButton.disabled = false;
216+
}

0 commit comments

Comments
 (0)