A rails application is invoking
<div id="sourceSelectPanel" style="display:none">
<label for="sourceSelect">Change video source:</label>
<select id="sourceSelect" style="max-width:400px">
</select>
</div>
<a class="button" id="resetButton">Stop</a>
<a class="button" id="startButton">Go</a>
a javascript library and then initializing the interface.
The console is given the expected ZXing code reader initialized
however a number of errors are occuring subsequently. Specifically:
Error: Can't enumerate devices, method not supported.
listVideoInputDevices
getVideoInputDevices
This was adopted mainly from a suggested example. Of note: one line has changed over time from codeReader.getVideoInputDevices()
to codeReader.listVideoInputDevices()
. Effecting that changes sitll hits the two errors.
But the peculiarity is, sometimes it works and presents the list of devices(cameras), mostly not. When it does, On occasion it reacts to the submission of startButton
and the content of the camera appears in the video div
<video id="video" width="320" height="180" style="border: 1px solid gray"></video>
What is going wrong here? Follows is the javascript for this use case
<script type="text/javascript">
window.addEventListener('load', function () {
let selectedDeviceId;
const codeReader = new ZXing.BrowserMultiFormatReader()
console.log('ZXing code reader initialized')
codeReader.getVideoInputDevices()
.then((videoInputDevices) => {
const sourceSelect = document.getElementById('sourceSelect')
selectedDeviceId = videoInputDevices[0].deviceId
if (videoInputDevices.length >= 1) {
videoInputDevices.forEach((element) => {
const sourceOption = document.createElement('option')
sourceOption.text = element.label
sourceOption.value = element.deviceId
sourceSelect.appendChild(sourceOption)
})
sourceSelect.onchange = () => {
selectedDeviceId = sourceSelect.value;
};
const sourceSelectPanel = document.getElementById('sourceSelectPanel')
sourceSelectPanel.style.display = 'block'
}
document.getElementById('startButton').addEventListener('click', () => {
codeReader.decodeFromVideoDevice(selectedDeviceId, 'video', (result, err) => {
if (result) {
console.log(result)
document.getElementById('result').textContent = result.text
let formData = new FormData();
let CodeParams = {
code_data: result.text,
shop_id: <%= current_shop.id %>
};
formData.append("code_json_data", JSON.stringify(CodeParams));
$.ajax({
url: "new_movement",
type: "post",
data: formData,
processData: false,
contentType: false,
});
}
if (err && !(err instanceof ZXing.NotFoundException)) {
console.error(err)
document.getElementById('result').textContent = err
}
})
console.log(`Started continous decode from camera with id ${selectedDeviceId}`)
})
document.getElementById('resetButton').addEventListener('click', () => {
codeReader.reset()
document.getElementById('result').textContent = '';
console.log('Reset.')
})
})
.catch((err) => {
console.error(err)
})
})
It turns out, the script requires a browser SSL connection. Not just on the JS, but the enveloping page as well.
The fact that things ran on localhost (there is an exception for that) but also partially (the devices menu would ocasionally appear) and the console states ZXing code reader initialized
are confounding elements.