Browse Source

webrtc: add options (width, height, framerate, audio capture) and store parameters in URL (#1837) (#2167) (#2584)

pull/2626/head
Lukinoh 2 years ago committed by GitHub
parent
commit
107a9a4281
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 216
      internal/core/webrtc_publish_index.html

216
internal/core/webrtc_publish_index.html

@ -26,21 +26,27 @@ body { @@ -26,21 +26,27 @@ body {
justify-content: center;
min-height: 200px;
padding: 10px;
flex-direction: column;
}
#device {
flex-direction: column;
display: grid;
grid-template-rows: repeat(6, 1fr);
grid-auto-flow: column;
gap: 10px 20px
}
#device > div {
margin: 10px 0;
display: flex;
.item {
display: grid;
grid-auto-flow: column;
grid-template-columns: auto 200px;
gap: 20px;
justify-content: center;
flex-wrap: wrap;
}
#device > div > div {
display: flex;
gap: 20px;
#submit_line {
margin-top: 20px;
}
#error-message {
text-align: center;
}
@ -56,65 +62,81 @@ select { @@ -56,65 +62,81 @@ select {
<div id="initializing" style="display: block;">
initializing
</div>
<div id="device" style="display: none;">
<div id="device_line">
<div>
video device
<div id="device" style="display: none">
<div class="item">
<label for="video_device">video device</label>
<select id="video_device">
<option value="none">none</option>
</select>
</div>
<div>
audio device
<select id="audio_device">
<option value="none">none</option>
<div class="item">
<label for="video_codec">video codec</label>
<select id="video_codec">
</select>
</div>
<div class="item">
<label for="video_bitrate">video bitrate (kbps)</label>
<input id="video_bitrate" type="text" value="10000" />
</div>
<div id="codec_line">
<div>
video codec
<select id="video_codec">
<div class="item">
<label for="video_framerate">video framerate</label>
<input id="video_framerate" type="text" value="30" />
</div>
<div class="item">
<label for="video_width">video width</label>
<input id="video_width" type="text" value="1920" />
</div>
<div class="item">
<label for="video_height">video height</label>
<input id="video_height" type="text" value="1080" />
</div>
<div class="item">
<label for="audio_device">audio device</label>
<select id="audio_device">
<option value="none">none</option>
</select>
</div>
<div>
audio codec
<div class="item">
<label for="audio_codec">audio codec</label>
<select id="audio_codec">
</select>
</div>
</div>
<div id="bitrate_line">
<div>
video bitrate (kbps)
<input id="video_bitrate" type="text" value="10000" />
</div>
<div>
audio bitrate (kbps)
<div class="item">
<label for="audio_bitrate">audio bitrate (kbps)</label>
<input id="audio_bitrate" type="text" value="32" />
</div>
<div>
<input id="audio_voice" type="checkbox" checked>
<div class="item">
<label for="audio_voice">optimize for voice</label>
<input id="audio_voice" type="checkbox" checked>
</div>
<div class="item"></div>
</div>
<div id="submit_line">
<div id="submit_line" style="display: none">
<button id="publish_confirm">publish</button>
</div>
</div>
<div id="transmitting" style="display: none;">
publishing
</div>
<div id="error" style="display: none;">
<span id="error-message"></span>
</div>
</div>
<script>
const INITIALIZING = 0;
const DEVICE = 1;
const TRANSMITTING = 2;
@ -123,14 +145,83 @@ const ERROR = 3; @@ -123,14 +145,83 @@ const ERROR = 3;
let state = INITIALIZING;
let errorMessage = '';
const videoForm = {
device: document.getElementById("video_device"),
codec: document.getElementById("video_codec"),
bitrate: document.getElementById("video_bitrate"),
framerate: document.getElementById("video_framerate"),
width: document.getElementById("video_width"),
height: document.getElementById("video_height")
}
const audioForm = {
device: document.getElementById("audio_device"),
codec: document.getElementById("audio_codec"),
bitrate: document.getElementById("audio_bitrate"),
voice: document.getElementById("audio_voice"),
}
const url = new URL(window.location.href);
const initializeInputsFromUrl = () => {
const inputs = [...Object.values(videoForm), ...Object.values(audioForm)]
for (const input of inputs) {
const value = url.searchParams.get(input.id);
if (value) {
if (input instanceof HTMLInputElement && input.type === "text") {
input.value = value;
}
if (input instanceof HTMLInputElement && input.type === "checkbox") {
input.checked = value === "true";
}
if (input instanceof HTMLSelectElement) {
input.value = value
}
}
}
}
const registerInputsToUrl = () => {
const inputs = [...Object.values(videoForm), ...Object.values(audioForm)]
for (const input of inputs) {
if (input instanceof HTMLInputElement && input.type === "text") {
input.addEventListener("input", () => {
url.searchParams.set(input.id, input.value);
window.history.replaceState(null, null, url);
})
}
if (input instanceof HTMLInputElement && input.type === "checkbox") {
input.addEventListener("input", () => {
url.searchParams.set(input.id, input.checked);
window.history.replaceState(null, null, url);
})
}
if (input instanceof HTMLSelectElement) {
input.addEventListener("input", () => {
url.searchParams.set(input.id, input.value);
window.history.replaceState(null, null, url);
})
}
}
}
const render = () => {
for (const el of ['initializing', 'device', 'transmitting', 'error']) {
for (const el of ['initializing', 'device', 'submit_line', 'transmitting', 'error']) {
document.getElementById(el).style.display = 'none';
}
switch (state) {
case DEVICE:
document.getElementById('device').style.display = 'flex';
document.getElementById('device').style.display = 'grid';
document.getElementById('submit_line').style.display = 'block';
initializeInputsFromUrl();
registerInputsToUrl();
break;
case TRANSMITTING:
@ -323,7 +414,7 @@ class Transmitter { @@ -323,7 +414,7 @@ class Transmitter {
start() {
console.log("requesting ICE servers");
fetch(new URL('whip', window.location.href) + window.location.search, {
fetch(new URL('whip', url) + url.search, {
method: 'OPTIONS',
})
.then((res) => this.onIceServers(res))
@ -355,7 +446,7 @@ class Transmitter { @@ -355,7 +446,7 @@ class Transmitter {
console.log("sending offer");
fetch(new URL('whip', window.location.href) + window.location.search, {
fetch(new URL('whip', url) + url.search, {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
@ -366,7 +457,7 @@ class Transmitter { @@ -366,7 +457,7 @@ class Transmitter {
if (res.status !== 201) {
throw new Error('bad status code');
}
this.sessionUrl = new URL(res.headers.get('location'), window.location.href).toString();
this.sessionUrl = new URL(res.headers.get('location'), url.href).toString();
return res.text();
})
.then((sdp) => this.onRemoteAnswer(new RTCSessionDescription({
@ -396,14 +487,13 @@ class Transmitter { @@ -396,14 +487,13 @@ class Transmitter {
if (this.restartTimeout !== null) {
return;
}
editAnswer(
answer,
document.getElementById('video_codec').value,
document.getElementById('audio_codec').value,
document.getElementById('video_bitrate').value,
document.getElementById('audio_bitrate').value,
document.getElementById('audio_voice').value,
videoForm.codec.value,
audioForm.codec.value,
videoForm.bitrate.value,
audioForm.bitrate.value,
audioForm.voice.checked,
);
this.pc.setRemoteDescription(answer);
@ -491,8 +581,8 @@ const onPublish = () => { @@ -491,8 +581,8 @@ const onPublish = () => {
state = TRANSMITTING;
render();
const videoId = document.getElementById('video_device').value;
const audioId = document.getElementById('audio_device').value;
const videoId = videoForm.device.value;
const audioId = audioForm.device.value;
if (videoId !== 'screen') {
let video = false;
@ -509,7 +599,7 @@ const onPublish = () => { @@ -509,7 +599,7 @@ const onPublish = () => {
deviceId: audioId,
};
const voice = document.getElementById('audio_voice').checked;
const voice = audioForm.voice.checked;
if (!voice) {
audio.autoGainControl = false;
audio.echoCancellation = false;
@ -527,12 +617,12 @@ const onPublish = () => { @@ -527,12 +617,12 @@ const onPublish = () => {
} else {
navigator.mediaDevices.getDisplayMedia({
video: {
width: { ideal: 1920 },
height: { ideal: 1080 },
frameRate: { ideal: 30 },
width: { ideal: videoForm.width.value },
height: { ideal: videoForm.height.value },
frameRate: { ideal: videoForm.framerate.value },
cursor: "always",
},
audio: false,
audio: true,
})
.then(onTransmit)
.catch((err) => {
@ -553,7 +643,7 @@ const populateDevices = () => { @@ -553,7 +643,7 @@ const populateDevices = () => {
const opt = document.createElement('option');
opt.value = device.deviceId;
opt.text = device.label;
document.getElementById('video_device').appendChild(opt);
videoForm.device.appendChild(opt);
}
break;
@ -562,7 +652,7 @@ const populateDevices = () => { @@ -562,7 +652,7 @@ const populateDevices = () => {
const opt = document.createElement('option');
opt.value = device.deviceId;
opt.text = device.label;
document.getElementById('audio_device').appendChild(opt);
audioForm.device.appendChild(opt);
}
break;
}
@ -572,15 +662,15 @@ const populateDevices = () => { @@ -572,15 +662,15 @@ const populateDevices = () => {
const opt = document.createElement('option');
opt.value = "screen";
opt.text = "screen";
document.getElementById('video_device').appendChild(opt);
videoForm.device.appendChild(opt);
}
if (document.getElementById('video_device').children.length !== 0) {
document.getElementById('video_device').value = document.getElementById('video_device').children[1].value;
if (videoForm.device.children.length !== 0) {
videoForm.device.value = videoForm.device.children[1].value;
}
if (document.getElementById('audio_device').children.length !== 0) {
document.getElementById('audio_device').value = document.getElementById('audio_device').children[1].value;
if (audioForm.device.children.length !== 0) {
audioForm.device.value = audioForm.device.children[1].value;
}
});
};
@ -599,7 +689,7 @@ const populateCodecs = () => { @@ -599,7 +689,7 @@ const populateCodecs = () => {
const opt = document.createElement('option');
opt.value = codec;
opt.text = codec.split('/')[0].toUpperCase();
document.getElementById('video_codec').appendChild(opt);
videoForm.codec.appendChild(opt);
}
}
@ -608,7 +698,7 @@ const populateCodecs = () => { @@ -608,7 +698,7 @@ const populateCodecs = () => {
const opt = document.createElement('option');
opt.value = codec;
opt.text = codec.split('/')[0].toUpperCase();
document.getElementById('audio_codec').appendChild(opt);
audioForm.codec.appendChild(opt);
}
}

Loading…
Cancel
Save