使用getUserMedia获得最大的视频分辨率

时间:2014-12-11 10:28:10

标签: javascript html5 video webrtc

我正试图通过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”,因为在这种情况下我将得到标准的低分辨率。我不能问视频“不低于一些合理的小分辨率”,因为可能有更高分辨率的用户,我想获得更高的分辨率。

7 个答案:

答案 0 :(得分:14)

我仍然不知道答案是否正确,但我会做以下事情:

video: {
  optional: [
    {minWidth: 320},
    {minWidth: 640},
    {minWidth: 1024},
    {minWidth: 1280},
    {minWidth: 1920},
    {minWidth: 2560},
  ]
}

虽然单个minWidth: 2560表达式将分辨率重置为默认值,但系列minWidth表达式使浏览器始终在经过测试的硬件上获得最大分辨率。

答案 1 :(得分:11)

使用:

var constraints = { 
    video: {
        width: { ideal: 4096 },
        height: { ideal: 2160 } 
    } 
};

这将使浏览器使用最高可用分辨率,最高可达4K。适用于Chrome 63,Edge 41和Firefox 58。

引用MDN关于使用理想

  

理想值在使用时具有重力,这意味着浏览器   将尝试找到设置(和相机,如果你有多个),   与给定的理想值之间的最小适合距离。

答案 2 :(得分:7)

我在定义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);
});

答案 3 :(得分:5)

仍然没有找到任何好的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。网络摄像头C270 测试了此实施。但我认为这个解决方案应该适用于每个场景。谢谢。

答案 4 :(得分:3)

我同意他的观点,他的方法很好: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

答案 5 :(得分:0)

您可以检查此实用程序以检查设备的可用分辨率:

https://webrtchacks.github.io/WebRTC-Camera-Resolution/

它可用于故障排除。

希望你觉得它很有趣!

答案 6 :(得分:0)

您始终可以在轨道上结合使用applyConstraints()getCapabilities()Honza Kalfus' answer声称chrome现在可以处理ideal道具以解决问题。我没有对此进行测试,但是Chrome 83仍然可以为frameRate提供理想的值,并且如果超出了可承受的范围,则根本不会开始播放视频...因此,我希望这对某人有帮助。

stream = await navigator.mediaDevices.getUserMedia({ video: { width: 100, height: 100, frameRate: { min: 8, max:60 }, facingMode: 'environment' } });
track = stream.getTracks()[0];
var frIdeal = 35;
constrs = track.getConstraints();
frCap = track.getCapabilities().frameRate;
if (frCap && "min" in frCap && "max" in frCap) {
  constrs.frameRate = Math.max(frCap.min, Math.min(frCap.max, frIdeal));
  track.applyConstraints(constrs);
}

如果这是最大值(Chrome83),这将给我30hz。

另请参阅MDN docs