Получить максимальное разрешение видео с помощью getUserMedia
Я пытаюсь получить максимально возможное видео разрешение через JS navigator.getUserMedia
. Я знаю о ограничениях, но не знаю, как правильно выбрать в моем случае.
Проблема заключается в том, что нет способа сказать "Я хочу видео с максимальным разрешением". Поэтому вместо этого я пытаюсь сказать "Я хочу видео не менее, чем очень большое разрешение".
Когда я пытаюсь minWidth: 1600
, Chrome возвращает мне 1280 × 720 видео (максимально возможное для моей камеры, я думаю). Но что делать, если у пользователя есть камера с более высоким разрешением? Поэтому я запрашиваю видео minWidth: 2048
, а Chrome возвращает только 640 × 480.
var constraints = {
video: {
optional: [
{minWidth: 2048}
]
}
};
Это онлайн-пример: http://jsbin.com/kibeza/1/watch?js,output
И есть настоящая проблема: Chrome не знает математику. Он думает, что 1600 больше, чем 2048. Я не могу просить видео "не менее 100500", потому что в этом случае я получу стандартное низкое разрешение. Я не могу спросить видео "не менее разумного малого разрешения", потому что могут быть пользователи с более высоким разрешением, и я хочу получить более высокое разрешение.
Ответы
Ответ 1
Я до сих пор не знаю правильного ответа, но я делаю следующее:
video: {
optional: [
{minWidth: 320},
{minWidth: 640},
{minWidth: 1024},
{minWidth: 1280},
{minWidth: 1920},
{minWidth: 2560},
]
}
Пока одно выражение minWidth: 2560
сбрасывает разрешение по умолчанию, серия выражения minWidth
делает браузер всегда принимает максимальное разрешение на тестируемом оборудовании.
Ответ 2
Тем не менее, я не нашел никакого хорошего API для получения максимального разрешения видео с помощью getUserMedia.
Но здесь я разделяю идею , чтобы получить максимальное поддерживаемое разрешение видео подключенного устройства с помощью алгоритма двоичного поиска, и он отлично работает.
Вот шаги для выполнения этой задачи,
- Сохранение некоторых стандартных разрешений в массиве, сохранение по возрастанию
порядок.
- Установите leftIndex= 0 и rightIndex= размер массива разрешений.
- Отметьте midIndex= (левый + правый)/2 разрешенный или нет, и
измените влево и вправо на основе результата.
Здесь я делюсь своей реализацией:
var ResolutionsToCheck = [
{width: 160, height:120},
{width: 320, height:180},
{width: 320, height:240},
{width: 640, height:360},
{width: 640, height:480},
{width: 768, height:576},
{width: 1024, height:576},
{width: 1280, height:720},
{width: 1280, height:768},
{width: 1280, height:800},
{width: 1280, height:900},
{width: 1280, height:1000},
{width: 1920, height:1080},
{width: 1920, height:1200},
{width: 2560, height:1440},
{width: 3840, height:2160},
{width: 4096, height:2160}
];
var left = 0;
var right = ResolutionsToCheck.length;
var selectedWidth;
var selectedHeight;
var mid;
function FindMaximum_WidthHeight_ForCamera()
{
console.log("left:right = ", left, ":", right);
if(left > right)
{
console.log("Selected Height:Width = ", selectedWidth, ":", selectedHeight);
return;
}
mid = Math.floor((left + right) / 2);
var temporaryConstraints = {
"audio": true,
"video": {
"mandatory": {
"minWidth": ResolutionsToCheck[mid].width,
"minHeight": ResolutionsToCheck[mid].height,
"maxWidth": ResolutionsToCheck[mid].width,
"maxHeight": ResolutionsToCheck[mid].height
},
"optional": []
}
}
navigator.mediaDevices.getUserMedia(temporaryConstraints).then(checkSuccess).catch(checkError);
}
function checkSuccess(stream)
{
console.log("Success for --> " , mid , " ", ResolutionsToCheck[mid]);
selectedWidth = ResolutionsToCheck[mid].width;
selectedHeight = ResolutionsToCheck[mid].height;
left = mid+1;
for (let track of stream.getTracks())
{
track.stop()
}
FindMaximum_WidthHeight_ForCamera();
}
function checkError(error)
{
console.log("Failed for --> " + mid , " ", ResolutionsToCheck[mid], " ", error);
right = mid-1;
FindMaximum_WidthHeight_ForCamera();
}
Просто вызовите функцию FindMaximum_WidthHeight_ForCamera(). Когда операция будет завершена, максимальное разрешение видео будет сохранено в переменных selectedWidth и selectedHeight. Здесь я также добавляю консольный вывод для своего устройства:
//Console Output
left:right = 0 : 17
Success for --> 8 Objectheight: 768width: 1280__proto__: Object
left:right = 9 : 17
Failed for --> 13 Objectheight: 1200width: 1920__proto__: Object NavigatorUserMediaError
left:right = 9 : 12
Success for --> 10 Objectheight: 900width: 1280__proto__: Object
left:right = 11 : 12
Failed for --> 11 Objectheight: 1000width: 1280__proto__: Object NavigatorUserMediaError
left:right = 11 : 10
Selected Height:Width = 1280 : 900
Я протестировал эту реализацию, используя версию Chrome версии 57.0.2987.110 (64-разрядная версия) и Logitech, Inc. Webcam C270. Но я думаю, что это решение должно работать в каждом сценарии. Спасибо.
Ответ 3
Я согласен с homm, его подход отлично работает: https://jsfiddle.net/evpozdniakov/c84ksucw/
var getUserMediaPrefixed,
videoStream,
videoTag;
setGumPrefix();
if (!getUserMediaPrefixed) {
logMessage('Sorry, your browser doesn\'t support getUserMedia interface');
}
else {
runCamera();
}
function dealWithStream(stream) {
videoStream = stream;
if (!videoTag) {
videoTag = document.createElement('video');
videoTag.addEventListener('resize', videoEventListener);
}
videoTag.src = window.URL.createObjectURL(stream);
videoTag.play();
}
function handleError(e) {
if (e.name == 'PermissionDeniedError') {
logMessage('It looks like you\'ve denied access to the camera.');
}
else if (e.name == 'SourceUnavailableError') {
logMessage('It looks like your camera is <b>used</b> by another application.');
}
else {
logMessage('The camera is unavailable. The error message is: ' +e.message);
}
}
function logMessage(msg) {
var p = document.createElement('p');
p.innerHTML = msg;
document.getElementById('output').appendChild(p);
}
function runCamera() {
var constraints = {
audio: false,
video: {
optional: [
{minWidth: 320},
{minWidth: 640},
{minWidth: 800},
{minWidth: 900},
{minWidth: 1024},
{minWidth: 1280},
{minWidth: 1920},
{minWidth: 2560}
]
}
};
navigator[getUserMediaPrefixed](constraints, dealWithStream, handleError);
}
function setGumPrefix() {
if (navigator.getUserMedia) {
getUserMediaPrefixed = 'getUserMedia';
}
else if (navigator.webkitGetUserMedia) {
getUserMediaPrefixed = 'webkitGetUserMedia';
}
else if (navigator.mozGetUserMedia) {
getUserMediaPrefixed = 'mozGetUserMedia';
}
else if (navigator.msGetUserMedia) {
getUserMediaPrefixed = 'msGetUserMedia';
}
}
function videoEventListener() {
if (videoTag.videoWidth) {
logMessage('Best captured video quality in your browser is ' +videoTag.videoWidth+ '×' +videoTag.videoHeight);
// stop stream
videoStream.stop();
videoTag.src = '';
}
}
В моем случае Opera и Chrome предлагают максимальное разрешение 1280 × 720.
Firefox дает по умолчанию 640 × 480, но вы можете улучшить его разрешение и до 1280 × 720. Вот вы:
![enter image description here]()
Ответ 4
У меня был большой успех с определением размеров ideal
и попыткой принудительной "обратной" камеры.
$video = document.getElementById('video')
//declare ideal values
var constraints = {
audio: false,
video: {
width: { ideal: 1280 },
height: { ideal: 1024 },
facingMode: "environment"
}
};
// enumerate devices and select the first camera (mostly the back one)
navigator.mediaDevices.enumerateDevices().then(function(devices) {
for (var i = 0; i !== devices.length; ++i) {
if (devices[i].kind === 'videoinput') {
console.log('Camera found: ', devices[i].label || 'label not found', devices[i].deviceId || 'id no found');
videoConstraints.deviceId = { exact: devices[i].deviceId }
}
}
});
//first up the stream
navigator.mediaDevices.getUserMedia(constraints).then(function(stream) {
$video.srcObject = stream;
// log the real size
console.log($video.videoWidth, $video.videoHeight);
}).catch(function(err) {
console.log(err.name + ': ' + err.message);
});