quickwebrtc/index.html
Piotr Dobrowolski 31293e2141 index: quick hacky fixes for recent browsers
* fixup screen capture api changes
* require mouse click before screen capture
* better ICE logging
* vendor webrtc adapter
2022-07-10 22:10:12 +02:00

260 lines
6.6 KiB
HTML

<script src="/adapter-latest.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var hash = location.hash.substring(1).split('/');
if (adapter.browserDetails.browser == 'firefox' && (hash[1] === 'window' || hash[1] == 'screen' || hash[1] == 'tab')) {
adapter.browserShim.shimGetDisplayMedia(window, hash[1]);
}
var room = hash[0] || 'test-room';
var id = Math.random().toString(26).substring(2);
var receiver = hash[1] === 'recv';
var socket;
function socketConnect() {
socket = io.connect();
socket.on('connect', function () {
console.info('Connected to', room, id, receiver);
socket.emit('join', {id, room});
socket.emit('message', {id, room, type: 'joined'});
});
socket.on('message', async function (data) {
if (data.id === id)
return;
if (data.type === 'joined') {
var conn = await getPeerConnection(data.id, true);
} else if (data.type === 'ice' && data.peer === id) {
console.info('Remote ICE candidate:', JSON.stringify(data.ice))
var conn = await getPeerConnection(data.id);
conn.addIceCandidate(data.ice).catch(e => {
console.log("Failure during addIceCandidate(): " + e.name);
});
} else if (data.type === 'offer' && data.peer === id) {
if (!receiver) {
console.info('Requesting media...')
var stream = document.getElementById("vlocal").srcObject;
}
var conn = await getPeerConnection(data.id, false);
if (stream) {
console.info('Adding stream')
conn.addStream(stream);
}
await conn.setRemoteDescription(new RTCSessionDescription(data.sdp));
var answer = await conn.createAnswer();
await conn.setLocalDescription(answer);
socket.emit('message', {
id, room, peer: data.id,
type: 'answer', sdp: conn.localDescription
})
} else if (data.type === 'answer' && data.peer === id) {
console.info('Session answer get:', data)
var conn = await getPeerConnection(data.id, false);
conn.setRemoteDescription(new RTCSessionDescription(data.sdp)); //.catch(report);
}
});
}
var peers = {};
async function getMedia() {
if (hash[1] === 'screen' || hash[1] === 'window' || hash[1] === 'tab') {
return new Promise((resolve,reject) => {
document.addEventListener('click', resolve);
}).then(() => navigator.mediaDevices.getDisplayMedia({
video: {
width: 1920,
height: 1080,
frameRate: 30,
cursor: "always",
},
audio: {
echoCancellation: true,
noiseSuppression: true,
sampleRate: 44100
},
}));
} else {
return navigator.mediaDevices.getUserMedia({video: {width: 1280, height: 720}});
}
}
async function getPeerConnection(peer, createOffer) {
if (peers[peer] !== undefined)
return peers[peer];
console.info('Creating PeerConnection for', peer);
var conn = new RTCPeerConnection({
});
peers[peer] = conn;
conn.onicecandidate = function (event) {
console.info('Local ICE candidate:', JSON.stringify(event.candidate));
socket.emit('message', {
id, room, peer,
type: 'ice', ice: event.candidate
});
}
conn.oniceconnectionstatechange = function (event) {
switch (conn.iceConnectionState) {
case 'disconnected':
case 'failed':
peers[peer].videoElement.remove();
peers[peer].close();
peers[peer] = null;
break;
}
}
conn.ontrack = function (event) {
console.info('Got track:', event);
if (event.track.kind !== 'video') {
console.warn('ignoring')
return;
}
const mediaStream = new MediaStream();
if (conn.videoElement) {
var video = conn.videoElement;
} else {
var video = document.createElement('video');
video.setAttribute("title", peer);
if (receiver)
video.setAttribute("class", "receiver");
document.getElementById("peers").appendChild(video);
conn.videoElement = video;
}
mediaStream.addTrack(event.track)
video.srcObject = mediaStream;
video.onloadedmetadata = function (e) {
video.play();
}
}
conn.onaddstream = function (event) {
console.info('Got stream:', event.stream);
/*var video = document.getElementById("vremote")
video.srcObject = event.stream;
video.onloadedmetadata = function(e) {
video.play();
}*/
}
if (createOffer) {
if (!receiver) {
var video = document.getElementById("vlocal");
conn.addStream(video.srcObject);
}
var datachannel = conn.createDataChannel('sendDataChannel');
var offer = await conn.createOffer({offerToReceiveAudio: true, offerToReceiveVideo: true});
await conn.setLocalDescription(offer);
socket.emit('message', {
id, room, peer,
type: 'offer',
sdp: conn.localDescription
});
}
return conn;
}
function report(err) {
console.info(err);
}
document.addEventListener("DOMContentLoaded", async function () {
if (!receiver) {
var elem = document.documentElement;
try {
var stream = await getMedia();
var video = document.getElementById("vlocal");
video.srcObject = stream;
video.onloadedmetadata = function (e) {
video.play();
}
} catch (e) {
console.error("media", e)
}
}
document.getElementById("room").innerText = room;
socketConnect();
});
</script>
<style>
video {
max-width: 100%;
}
html,
body {
height: 100%;
margin: 0;
}
#vlocal,
.receiver {
z-index: -10;
position: fixed;
right: 0;
bottom: 0;
min-width: 100%;
min-height: 100%;
max-height: 100%;
}
#peers {
padding: 10px;
}
#peers video {
border: 3px solid red;
max-width: 100px;
}
#peers video.receiver {
filter: none;
border: none;
background: black;
}
#vremote {
border: 5px solid green;
}
pre {
position: absolute;
bottom: 0;
text-align: center;
width: 100%;
background: rgba(255, 255, 255, 0.5);
padding: 10px 0px;
margin: 0;
}
</style>
<video id="vlocal"></video>
<div id="peers"></div>
<pre>Stream using <strong>https://3000.f.inf.re/#<span id="room"></span></strong> (append /screen or /window on firefox to do screencasting)</pre>
<!--<video id="vremote"></video>-->