-
Notifications
You must be signed in to change notification settings - Fork 0
/
gum.html
266 lines (220 loc) · 9.24 KB
/
gum.html
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>getUserMedia</title>
<style>
body {
background-color: #333;
color: #fff;
}
video {
/*opacity: 20%; */
/*
height: 720px;
width: 1280px;
*/
}
table, th, td {
border: 1px solid grey;
border-collapse: collapse;
text-align: right;
}
td:first-child {
text-align: left;
}
</style>
</head>
<body>
<video id="source" autoplay playsinline controls></video>
<video id="cloneVid" autoplay playsinline muted controls hidden="hidden"></video>
<br>
<label for="audioInput">Audio Input:</label>
<input type="checkbox" id="audioInput">
<label for="videoInput">Video Input:</label>
<input type="checkbox" id="videoInput" checked>
<br>
<button id="start">Start</button>
<button id="stop">Stop</button>
<button id="shrink">Shrink</button>
<button id="grow">Grow</button>
<button id="clone">Clone</button>
<br>
<label for="audioDeviceList">Audio Device:</label>
<select id="audioDeviceList"></select>
<label for="videoDeviceList">Video Device:</label>
<select id="videoDeviceList"></select>
<br>
<div id="stats"></div>
<script type="module">
window.onload = async () => {
console.log("Window loaded");
}
// wait until the document and scripts are loaded using a promise await
await new Promise(resolve=>{
document.addEventListener('DOMContentLoaded', async () => {
console.log("DOM loaded");
resolve("DOM loaded");
});
});
const devicesBtn = document.querySelector('button#devices');
const audioDeviceList = document.getElementById('audioDeviceList');
const videoDeviceList = document.getElementById('videoDeviceList');
const startBtn = document.querySelector('button#start');
const stopBtn = document.querySelector('button#stop');
const stats = document.querySelector('div#stats');
const cloneBtn = document.querySelector('button#clone');
const shrinkBtn = document.querySelector('button#shrink');
const growBtn = document.querySelector('button#grow');
const video = document.querySelector('video#source');
let stream;
let devices = [];
// Device selection
function updateDeviceList(devices) {
audioDeviceList.innerHTML = '';
videoDeviceList.innerHTML = '';
devices.forEach(device => {
const option = document.createElement('option');
option.value = device.deviceId;
option.text = device.label || `Device ${device.deviceId}`;
if (device.kind === 'audioinput') {
audioDeviceList.appendChild(option);
} else if (device.kind === 'videoinput') {
videoDeviceList.appendChild(option);
}
});
}
[audioDeviceList, videoDeviceList].forEach(device=>device.onclick = async () => {
if(devices.length === 0) {
devices = await navigator.mediaDevices.enumerateDevices();
updateDeviceList(devices);
}
});
navigator.mediaDevices.ondevicechange = async () => {
devices = await navigator.mediaDevices.enumerateDevices();
updateDeviceList(devices);
};
audioDeviceList.addEventListener('change', () => {
if (stream) {
stream.getTracks().forEach(track => track.stop());
}
getMedia();
});
videoDeviceList.addEventListener('change', () => {
if (stream) {
stream.getTracks().forEach(track => track.stop());
}
getMedia();
});
function clone() {
const sourceTrack = stream.getVideoTracks()[0];
const cloneTrack = sourceTrack.clone();
window.cloneTrack = cloneTrack;
console.log("cloneTrack:", cloneTrack);
console.log("cloneTrack settings:", cloneTrack.getSettings());
console.log("cloneTrack constraints:", cloneTrack.getConstraints());
console.log("cloneTrack capabilities:", cloneTrack.getCapabilities());
const cloneStream = new MediaStream([cloneTrack]);
// video.srcObject = cloneStream;
const cloneVid = document.querySelector('video#cloneVid');
cloneVid.srcObject = cloneStream;
cloneVid.hidden = false;
window.cloneStream = cloneStream;
console.log("started cloned stream")
// window.sourceTrack = stream.getVideoTracks()[0];
// sourceTrack.stop();
}
async function getMedia() {
const audioDeviceId = audioDeviceList.value || undefined;
const videoDeviceId = videoDeviceList.value || undefined;
const audioInput = document.getElementById('audioInput').checked;
const videoInput = document.getElementById('videoInput').checked;
const constraints = {
video: videoInput ? {
height: { exact: 720 },
aspectRatio: 1.7777777778,
deviceId: videoDeviceId ? { exact: videoDeviceId } : undefined
} : false,
audio: audioInput ? {
deviceId: audioDeviceId ? { exact: audioDeviceId } : undefined
} : false
};
console.log("Before gUM");
stream = await navigator.mediaDevices.getUserMedia(constraints);
const [track] = stream.getVideoTracks();
console.log("Source track:", track);
console.log("Source track settings:", track.getSettings());
console.log("Source track constraints:", track.getConstraints());
console.log("Source track capabilities:", track.getCapabilities());
video.srcObject = stream;
window.stream = stream;
console.log("started camera stream")
window.sourceTrack = stream.getVideoTracks()[0];
}
startBtn.onclick = async () => {
await getMedia();
}
stopBtn.onclick = () => {
video.pause();
stream?.getTracks().forEach(track => track.stop());
console.log("stopped all tracks")
}
cloneBtn.onclick = () => clone();
shrinkBtn.onclick = () => {
const newHeight = video.style.height > 0 ? video.style.height / 2 : video.clientHeight / 2;
const newWidth = video.style.width > 0 ? video.style.width / 2 : video.clientWidth / 2;
video.style.height = `${newHeight}px`;
video.style.width = `${newWidth}px`;
console.log(`shrunk to ${newHeight} x ${newWidth}`);
}
growBtn.onclick = () => {
const newHeight = video.style.height > 0 ? video.style.height * 2 : video.clientHeight * 2;
const newWidth = video.style.width > 0 ? video.style.width * 2 : video.clientWidth * 2;
video.style.height = `${newHeight}px`;
video.style.width = `${newWidth}px`;
console.log(`grew to ${newHeight} x ${newWidth}`);
}
function calculateStats() {
let decodedFrames = 0,
droppedFrames = 0,
startTime = new Date().getTime(),
initialTime = new Date().getTime();
const interval = setInterval(function () {
//see if webkit stats are available; exit if they aren't
if (!video.webkitDecodedFrameCount) {
console.log("Video FPS calcs not supported");
clearInterval(interval);
}
//get the stats
else {
const currentTime = new Date().getTime();
let deltaTime = (currentTime - startTime) / 1000;
let totalTime = (currentTime - initialTime) / 1000;
startTime = currentTime;
// Calculate decoded frames per sec.
const currentDecodedFPS = (video.webkitDecodedFrameCount - decodedFrames) / deltaTime;
const decodedFPSavg = video.webkitDecodedFrameCount / totalTime;
decodedFrames = video.webkitDecodedFrameCount;
// Calculate dropped frames per sec.
const currentDroppedFPS = (video.webkitDroppedFrameCount - droppedFrames) / deltaTime;
const droppedFPSavg = video.webkitDroppedFrameCount / totalTime;
droppedFrames = video.webkitDroppedFrameCount;
//write the results to a table
stats.innerHTML =
"<table><tr><th>Type</th><th>Total</th><th>Avg</th><th>Current</th></tr>" +
"<tr><td>Decoded</td><td>" + decodedFrames + "</td><td>" + decodedFPSavg.toFixed() + "</td><td>" + currentDecodedFPS.toFixed() + "</td></tr>" +
"<tr><td>Dropped</td><td>" + droppedFrames + "</td><td>" + droppedFPSavg.toFixed() + "</td><td>" + currentDroppedFPS.toFixed() + "</td></tr>" +
"<tr><td>All</td><td>" + (decodedFrames + droppedFrames) + "</td><td>" + (decodedFPSavg + droppedFPSavg).toFixed() + "</td><td>" + (currentDecodedFPS + currentDroppedFPS).toFixed() + "</td></tr></table>" +
"Camera resolution: " + video.videoWidth + " x " + video.videoHeight + "<br>" +
"Video element size: " + video.clientWidth + " x " + video.clientHeight;
}
}, 1000);
}
video.addEventListener('loadeddata', (event) => {
console.log(`Actual stream height: ${video.videoHeight}`);
calculateStats();
});
// getMedia();
</script>
</body>
</html>