web-dev-qa-db-fra.com

Obtenez une résolution vidéo maximale avec getUserMedia

J'essaie d'obtenir la résolution vidéo la plus élevée possible grâce à JS navigator.getUserMedia. Je connais les contraintes, mais je ne sais pas comment choisir correctement dans mon cas.

Le problème, c'est qu'il n'y a aucun moyen de dire "Je veux une vidéo avec une résolution maximale". Alors au lieu de cela, j'essaie de dire: "Je veux une vidéo tout autant qu'une très grande résolution".

Lorsque j'essaie minWidth: 1600, Chrome me renvoie une vidéo 1280 × 720 (le plus haut possible pour mon appareil photo, je pense). Mais que se passe-t-il si l'utilisateur a une caméra avec une résolution plus élevée? Je demande donc une vidéo minWidth: 2048 et Chrome ne renvoie que 640 × 480.

var constraints = {
  video: {
    optional: [
    {minWidth: 2048}
    ]
  }
};

Ceci est un exemple en ligne: http://jsbin.com/kibeza/1/watch?js,output

Et il y a un problème: Chrome ne connaît pas les mathématiques. Il pense que 1600 est supérieur à 2048. Je ne peux pas demander de vidéo "pas moins de 100500", car dans ce cas, la résolution standard est basse. Je ne peux pas demander à la vidéo "pas moins qu'une résolution raisonnable", car il peut y avoir des utilisateurs avec une résolution plus élevée et je souhaite obtenir une résolution plus élevée.

24
homm

Je ne connais toujours pas la bonne réponse, mais je fais ce qui suit:

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

Alors que la seule expression minWidth: 2560 rétablit la résolution par défaut, la série d’expressions minWidth permet au navigateur de prendre toujours la résolution maximale sur le matériel testé.

13
homm

Utilisation:

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

Cela obligera le navigateur à utiliser la résolution maximale disponible, jusqu'à 4K. Fonctionne dans Chrome 63, Edge 41 et Firefox 58.

Citant MDN concernant l'utilisation de ideal:

Une valeur idéale, lorsqu'elle est utilisée, a la gravité, ce qui signifie que le navigateur va essayer de trouver le réglage (et la caméra, si vous en avez plusieurs), avec la plus petite distance de fitness par rapport aux valeurs idéales données.

8
Honza Kalfus

J'ai eu du succès avec la définition de ideal dimensions et en essayant de forcer la caméra de recul.

$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);
});
7
sidonaldson

Je n'ai toujours pas trouvé de bonne API pour obtenir une résolution vidéo maximale avec getUserMedia .

Mais je partage ici mon idée d’obtenir la résolution vidéo maximale prise en charge de l’appareil connecté à l’aide de algorithme de recherche binaire et cela fonctionne très bien.

Voici les étapes pour faire ce travail,

  • Stocke certaines résolutions standard dans un tableau, en maintenant l'ordre croissant
  • Définissez leftIndex = 0 et rightIndex = taille du tableau de résolution.
  • Vérifiez midIndex = (gauche + droite)/2 résolution prise en charge ou non, et Modifier gauche et droite en fonction du résultat.

Ici je partage mon implémentation: 

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();
}

Appelez simplementfunction FindMaximum_WidthHeight_ForCamera (). Lorsque l'opération sera terminée, la résolution vidéo maximale sera stockée dans selectedWidth et selectedHeight variables. Ici, je joins également une sortie de console pour mon appareil:

//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

J'ai testé cette implémentation avec Version Chrome 57.0.2987.110 (64 bits) et Logitech, Inc. Webcam C270 . Mais je pense que cette solution devrait fonctionner dans chaque scénario. Je vous remercie. 

5
RajibTheKing

Je suis d'accord avec homm, son approche fonctionne bien: 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 = '';
    }
}

Dans mon cas, Opera et Chrome offrent une résolution maximale de 1280 × 720.

Firefox donne 640 × 480 par défaut, mais vous pouvez améliorer sa résolution jusqu'à 1280 × 720. Voici:

enter image description here

3
evpozdniakov

Vous pouvez vérifier cet utilitaire pour vérifier les résolutions disponibles de vos appareils:

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

C'est utile pour le dépannage.

J'espère que vous le trouvez intéressant!

0
Andrés