|
|
@@ -7,15 +7,66 @@ |
|
|
|
body.justVideo { |
|
|
|
margin: 0; |
|
|
|
overflow: hidden; |
|
|
|
} |
|
|
|
#selfView { |
|
|
|
position: fixed; |
|
|
|
right: 0; |
|
|
|
bottom: 0; |
|
|
|
border: 5px solid blue; |
|
|
|
} |
|
|
|
#unmute { |
|
|
|
position: fixed; |
|
|
|
top: 0; |
|
|
|
width: 100%; |
|
|
|
font-size: 4em; |
|
|
|
} |
|
|
|
form { |
|
|
|
background: lightgray; |
|
|
|
border: solid gold 5px; |
|
|
|
display: inline-block; |
|
|
|
display: table; |
|
|
|
} |
|
|
|
form label { |
|
|
|
display: table-row; |
|
|
|
} |
|
|
|
#status { |
|
|
|
clear: both; |
|
|
|
} |
|
|
|
</style> |
|
|
|
</head> |
|
|
|
<body> |
|
|
|
<a id="qrcodelink" style="display:none;"><img id="qrcode" /></a> |
|
|
|
<span id="status"></span> |
|
|
|
<div id="videos" style="display:none;"> |
|
|
|
<video id="remoteView" width="100%" autoplay muted></video> |
|
|
|
<video id="selfView" width="200" height="150" autoplay></video> |
|
|
|
<form name="settings"> |
|
|
|
<label> |
|
|
|
Recieve remote video: |
|
|
|
<select name="client-video"> |
|
|
|
<option value="none">none</option> |
|
|
|
<option value="environment" selected>rear camera</option> |
|
|
|
<option value="user">front camera</option> |
|
|
|
<option value="screen">screen share</option> |
|
|
|
</select> |
|
|
|
</label> |
|
|
|
<label> |
|
|
|
Recieve remote audio: |
|
|
|
<input name="client-audio" type="checkbox" value="true" /> |
|
|
|
</label> |
|
|
|
<label> |
|
|
|
Transmit video: |
|
|
|
<select name="host-video"> |
|
|
|
<option value="none">none</option> |
|
|
|
<option value="screen">screen share</option> |
|
|
|
</select> |
|
|
|
</label> |
|
|
|
<label> |
|
|
|
Transmit audio: |
|
|
|
<input name="host-audio" type="checkbox" value="true" /> |
|
|
|
</label> |
|
|
|
</form> |
|
|
|
<div id="status"></div> |
|
|
|
<div id="videos"> |
|
|
|
<button id="unmute" style="display:none;">Unmute</button> |
|
|
|
<video id="remoteView" width="100%" autoplay muted style="display:none;"></video> |
|
|
|
<video id="selfView" width="200" height="150" autoplay muted style="display:none;"></video> |
|
|
|
</div> |
|
|
|
<script > |
|
|
|
const create = (container, type) => container.appendChild(document.createElement(type)); |
|
|
@@ -25,9 +76,27 @@ body.justVideo { |
|
|
|
const qrcode = document.getElementById("qrcode"); |
|
|
|
const qrcodelink = document.getElementById("qrcodelink"); |
|
|
|
const remoteView = document.getElementById("remoteView"); |
|
|
|
remoteView.style.display = 'none'; |
|
|
|
const selfView = document.getElementById("selfView"); |
|
|
|
const unmute = document.getElementById("unmute"); |
|
|
|
const form = document.forms["settings"]; |
|
|
|
|
|
|
|
out.innerText += "Loading...\n"; |
|
|
|
|
|
|
|
unmute.addEventListener("click", _ => { |
|
|
|
remoteView.muted = false; |
|
|
|
unmute.style.display = 'none'; |
|
|
|
}); |
|
|
|
|
|
|
|
var settings = undefined; |
|
|
|
function readSettingsForm() { |
|
|
|
const obj = {}; |
|
|
|
for (const el of form.elements) { |
|
|
|
obj[el.name] = el.type == 'checkbox' ? el.checked : el.value; |
|
|
|
el.disabled = true; |
|
|
|
} |
|
|
|
return obj; |
|
|
|
} |
|
|
|
|
|
|
|
function getRoomName() { |
|
|
|
JSON.parse(document.getElementById('room-name').textContent); |
|
|
|
} |
|
|
@@ -53,6 +122,7 @@ body.justVideo { |
|
|
|
} else { |
|
|
|
roomName = roomName.substring(1); |
|
|
|
qrcodelink.style.display = 'none'; |
|
|
|
form.style.display = 'none'; |
|
|
|
} |
|
|
|
|
|
|
|
out.innerText += "Room: " + roomName + "\n"; |
|
|
@@ -91,6 +161,7 @@ body.justVideo { |
|
|
|
remoteView.play(); |
|
|
|
out.innerText += "Set srcObject\n"; |
|
|
|
out.style.display = 'none'; |
|
|
|
form.style.display = 'none'; |
|
|
|
videos.style.display = ''; |
|
|
|
body.classList.add('justVideo'); |
|
|
|
}; |
|
|
@@ -98,15 +169,73 @@ body.justVideo { |
|
|
|
return pc; |
|
|
|
} |
|
|
|
|
|
|
|
async function receiveMessage(e) { |
|
|
|
if (pc === undefined) pc = createRTCPeerConnection(); |
|
|
|
// get a local stream, show it in a self-view and add it to be sent |
|
|
|
async function startStreaming() { |
|
|
|
const otherAudioSettings = isHost |
|
|
|
? settings['client-audio'] |
|
|
|
: settings['host-audio']; |
|
|
|
if (otherAudioSettings) { |
|
|
|
unmute.style.display = ''; |
|
|
|
} |
|
|
|
|
|
|
|
if (pc !== undefined) return; |
|
|
|
pc = createRTCPeerConnection(); |
|
|
|
|
|
|
|
const videoSettings = isHost |
|
|
|
? settings['host-video'] |
|
|
|
: settings['client-video']; |
|
|
|
out.innerText += "videoSettings=" + videoSettings; |
|
|
|
const audioSettings = isHost |
|
|
|
? settings['host-audio'] |
|
|
|
: settings['client-audio']; |
|
|
|
out.innerText += "audioSettings=" + audioSettings; |
|
|
|
|
|
|
|
if (videoSettings == 'screen') alert('screen share unsupported'); |
|
|
|
|
|
|
|
const videoConstraints = videoSettings == 'none' |
|
|
|
? false |
|
|
|
: { advanced: [{facingMode: videoSettings}] }; |
|
|
|
out.innerText += "Created videoConstraints.\n"; |
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({ |
|
|
|
audio: audioSettings, |
|
|
|
video: videoConstraints |
|
|
|
}); |
|
|
|
out.innerText += "Created stream.\n"; |
|
|
|
if (videoConstraints) { |
|
|
|
selfView.srcObject = stream; |
|
|
|
selfView.style.display = ''; |
|
|
|
} |
|
|
|
for (const track of stream.getTracks()) { |
|
|
|
out.innerText += "Added track.\n"; |
|
|
|
pc.addTrack(track, stream); |
|
|
|
} |
|
|
|
} |
|
|
|
function startStartingWithErorrHandling() { |
|
|
|
startStreaming() |
|
|
|
.then(() => { |
|
|
|
out.innerText += "startStreaming() finished.\n"; |
|
|
|
}) |
|
|
|
.catch(e => { |
|
|
|
out.innerText += "startStreaming() errored: " + e.message + "\n"; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
async function receiveMessage(e) { |
|
|
|
qrcode.style.display = 'none'; |
|
|
|
out.innerText += "In webSocket.onmessage...\n"; |
|
|
|
create(out, 'pre').innerText = e.data.split('\\r\\n').join('\r\n'); |
|
|
|
create(out, 'br'); |
|
|
|
const data = JSON.parse(e.data); |
|
|
|
if (data.description) { |
|
|
|
if (data.requestSettings) { |
|
|
|
settings = readSettingsForm(); |
|
|
|
sendJson({ |
|
|
|
settings: settings |
|
|
|
}); |
|
|
|
} else if (data.settings) { |
|
|
|
settings = data.settings; |
|
|
|
startStartingWithErorrHandling(); |
|
|
|
} else if (data.description) { |
|
|
|
startStartingWithErorrHandling(); |
|
|
|
await pc.setRemoteDescription(data.description); |
|
|
|
if (data.description.type == "offer") { |
|
|
|
out.innerText += "Got an offer...\n"; |
|
|
@@ -116,6 +245,7 @@ body.justVideo { |
|
|
|
}); |
|
|
|
} |
|
|
|
} else if (data.candidate) { |
|
|
|
startStartingWithErorrHandling(); |
|
|
|
out.innerText += "Adding ice candidate...\n"; |
|
|
|
await pc.addIceCandidate(data.candidate); |
|
|
|
} |
|
|
@@ -132,7 +262,10 @@ body.justVideo { |
|
|
|
out.innerText += "Created WebSocket.\n"; |
|
|
|
|
|
|
|
webSocket.onclose = function(e) { |
|
|
|
console.error('Web socket closed unexpectedly'); |
|
|
|
out.innerText += 'WebSocket closed unexpectedly: ' + e + '\n'; |
|
|
|
}; |
|
|
|
webSocket.onerror = function(e) { |
|
|
|
out.innerText += 'WebSocket error: ' + e + '\n'; |
|
|
|
}; |
|
|
|
|
|
|
|
webSocket.onmessage = receiveMessage; |
|
|
@@ -142,31 +275,10 @@ body.justVideo { |
|
|
|
|
|
|
|
webSocket = createWebSocket(); |
|
|
|
|
|
|
|
// get a local stream, show it in a self-view and add it to be sent |
|
|
|
async function startStreaming() { |
|
|
|
pc = createRTCPeerConnection(); |
|
|
|
|
|
|
|
const videoConstraints = { advanced: [{facingMode: "environment"}] }; |
|
|
|
out.innerText += "Created videoConstraints.\n"; |
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({ "audio": false, "video": videoConstraints }); |
|
|
|
out.innerText += "Created stream.\n"; |
|
|
|
selfView.srcObject = stream; |
|
|
|
for (const track of stream.getTracks()) { |
|
|
|
out.innerText += "Added track.\n"; |
|
|
|
pc.addTrack(track, stream); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (!isHost) { |
|
|
|
startStreaming() |
|
|
|
.then(() => { |
|
|
|
out.innerText += "startStreaming() finished.\n"; |
|
|
|
}) |
|
|
|
.catch(e => { |
|
|
|
out.innerText += "startStreaming() errored: " + e.message + "\n"; |
|
|
|
}) |
|
|
|
; |
|
|
|
webSocket.onopen = _ => sendJson({requestSettings: true}); |
|
|
|
} |
|
|
|
|
|
|
|
out.innerText += "Finished <script> block.\n"; |
|
|
|
</script> |
|
|
|
</body> |
|
|
|