Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ <h2 id="timecodeLabel">TIMECODE</h2>
</div>

<div class="flexContainerV" id="cameraControlExpandedBodyContainer">
<div id="videocontainer">
<video autoplay="true" id="videopreview">

</video>
<select id="webcamSelect" onchange="SelectPreviewCamera()">
<option value="-1">--Select a webcam--</option>
</select>
</div>
<div class="tableControl">
<h3>Connection</h3>
<table>
Expand Down Expand Up @@ -346,4 +354,4 @@ <h3>Color</h3>
</div>
</div>
</body>
</html>
</html>
23 changes: 22 additions & 1 deletion style.css
Original file line number Diff line number Diff line change
Expand Up @@ -467,4 +467,25 @@ table, td {

td, tr {
align-items: center;
}
}

/* video preview */

#videocontainer {
width: 400px;
height: 250px;
background: white;
position: absolute;
left: 800px;
}

#videopreview {

}


#webcamSelect {
top: -160px;
position: relative;
left: -300px;
}
48 changes: 46 additions & 2 deletions web-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,36 @@ var ci = 0; // Index into this array for the currently selected came
// cameras[ci] is used to reference the currently selected camera object

var WBMode = 0; // 0: balance, 1: tint
let PreviewCam = -1; // which camera to use for preview. -1: none
let currentStream; // current preview USB webcam stream


var defaultControlsHTML;

var unsavedChanges = [];

// Set everything up
function bodyOnLoad() {
async function bodyOnLoad() {
defaultControlsHTML = document.getElementById("allCamerasContainer").innerHTML;
try {
await navigator.mediaDevices.getUserMedia({ video: true });
} catch (err) {
console.error("Error acessing video devices:", err);
}
try {
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(device => device.kind === 'videoinput');
const select = document.getElementById('webcamSelect');
videoDevices.forEach((device, index) => {
const option = document.createElement('option');
// Use the device label if available; if not, fallback to a generic name.
option.text = device.label || `Camera ${index + 1}`;
option.value = device.deviceId;
select.appendChild(option);
});
} catch (err) {
console.error("Error enumerating devices:", err);
}
}

// Checks the hostname, if it replies successfully then a new BMCamera object
Expand Down Expand Up @@ -633,11 +655,33 @@ function loopHandler(callerString) {
cameras[ci].PUTdata("/transports/0/playback", playbackState);
}

async function SelectPreviewCamera() {
let previewcam = document.getElementById('webcamSelect').value;
if (currentStream) {
currentStream.getTracks().forEach(track => track.stop());
}

const constraints = {
video: {
deviceId: previewcam ? { exact: previewcam } : undefined
}
};
try {
currentStream = await navigator.mediaDevices.getUserMedia(constraints);
const video = document.getElementById('videopreview');
video.srcObject = currentStream;
} catch (err) {
console.error("Error starting video stream:", err);
}
}


/* Helper Functions */
function parseTimecode(timecodeBCD) {
let noDropFrame = timecodeBCD & 0b01111111111111111111111111111111; // The first bit of the timecode is 1 if "Drop Frame Timecode" is on. We don't want to include that in the display.
let decimalTCInt = parseInt(noDropFrame.toString(16), 10); // Convert the BCD number into base ten
let decimalTCString = decimalTCInt.toString().padStart(8, '0'); // Convert the base ten number to a string eight characters long
let finalTCString = decimalTCString.match(/.{1,2}/g).join(':'); // Put colons between every two characters
return finalTCString;
}
}