Снимок WebRTC с веб-камеры и сохранение его на сервере в PHP: iPhone Safari вылетает при разрешении выше 2096

1

У меня есть РАБОЧИЙ код, чтобы сделать снимок с веб-камеры и сохранить его на PHP через ajax ... но когда я пытаюсь использовать разрешение выше 2000, сафари-мобильный на iPhone вылетает, почему и как это исправить?

здесь, если я сделаюgetUserMedia({ video:{width: { ideal: 2096 => все в порядке

Но если я будуgetUserMedia({ video:{width: { ideal: 3096 => вылетает :(

HTML

<video id="precam" playsinline="true" muted autoplay style="max-width:90%;" ></video>
<canvas id="canvax" ></canvas>
<div onclick="sendToServer('ajaxanswer');">SAVE</div>
<div onclick="webcamFRONT();">SWITCH TO FRONT CAM</div>
<div id="ajaxanswer" ></div>

JAVASCRIPT

<script>
const videoPlayer = document.querySelector("#precam"); 
const canvas = document.querySelector("#canvax");

function webcamREAR () {
    navigator.mediaDevices.getUserMedia({ video:{width: { ideal: 2096 },facingMode: "environment"}, audio:false })
        .then(stream => videoPlayer.srcObject = stream)
        .catch(error => {console.error(error);});
}

function webcamFRONT () {
    navigator.mediaDevices.getUserMedia({ video:{width: { ideal: 2096 },facingMode: "user"}, audio:false })
        .then(stream => videoPlayer.srcObject = stream)
        .catch(error => {console.error(error);});
}
        
function wcanvasim () { 
    canvas.width = videoPlayer.videoWidth; canvas.height = videoPlayer.videoHeight;
    canvas.getContext("2d").drawImage(videoPlayer, 0, 0, canvas.width, canvas.height);
}

webcamREAR();

function sendToServer (divID) {
    var pcache = (Math.floor(Math.random() * 100000000) + 1);
    var params = "divID="+encodeURIComponent(divID)+"&canvablob="+encodeURIComponent(canvas.toDataURL());
    var xhr = new XMLHttpRequest(); xhr.open("POST", "/file.php?pcache="+pcache, true);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    xhr.onreadystatechange = function(e) { if (xhr.readyState == 4) { $("#"+divID).html(e.currentTarget.responseText) ; } }
    xhr.send(params);
}
</script>

PHP

<?php

$whereTOdeBlob = '/path/to/server/'.mt_rand().'.png';
$canvablob = ( $_REQUEST['canvablob'] ?? '' ) ;
$canva64 = explode('base64,',$canvablob)[1] ?? '';
file_put_contents(INCLUDE_PATH_ROOT.$whereTOdeBlob,base64_decode($canva64));

// CONVERT TO JPG
// ADD TO DATABASE
// ANY STUFF YOU WANT ;)

echo '<img src="'.$canvablob.'" />';

?>

******* Возникает вопрос: почему при большом разрешении сафари вылетает?

Теги:
iphone webrtc mobile-safari getusermedia
CodeFix

1 ответ

1
Лучший ответ

Ты используешь .toDataURL() чтобы закодировать это огромное изображение как файл .png без потерь . Это, вероятно, генерирует многомегабайтную строку, которую вы пытаетесь выполнить POST. Где-то по пути Safari, вероятно , исчерпает непрерывную оперативную память и гаки либо при выделении, либо при сборке мусора. Также вероятно, что размер полезной нагрузки вашего POST превышает максимум php .

Пытаться.toDataURL('image/jpeg', 0.3) чтобы получить изображение JPEG низкого качества, которое будет генерировать гораздо меньшую строку. Если это сработает, увеличьте качество (от 0,3 до 0,4, 0,5 и т. Д.).

Или, лучше, преобразуйте свой холст в двоичный объект Blob и опубликуйте его . Это займет меньше места, чем URL-адрес данных. Что-то вроде этого. Не, повторюсь, не отлажен.

function sendToServer (divID) {
    var pcache = (Math.floor(Math.random() * 100000000) + 1)
    canvas.toBlob (function (blob) {
      var xhr = new XMLHttpRequest()
      xhr.open("POST", "/file.php?pcache="+pcache, true);
      xhr.onreadystatechange = function (e) { 
        if (xhr.readyState == 4) 
           $("#"+divID).html(e.currentTarget.responseText) 
      }

      var fd = new FormData();
      fd.append('divID', divID)
      fd.append('canvaBlob', blob)
      xhr.send(fd)
    }, 'image/jpeg', 0.8)
}

Также попробуйте ограничить высоту изображения, а также ширину. Если ваша камера находится в портретном режиме и вы запрашиваете ширину 2K, вы можете получить высоту 4K, если позволите.getUserMedia() выберите ту высоту, которую пожелает; он подчиняется соотношению сторон по умолчанию.

Наконец, с практической точки зрения изображения с таким высоким разрешением обычно должны быть субдискретизированы перед их использованием. Изображения JPEG с более низким разрешением обычно соответствуют практическим требованиям. Так что просто снимайте изображения с низким разрешением. (Если вы фотограф, делающий фотографии для печати в глянцевых журналах, вы уже знаете об ограничениях камер iPhone.)

Поделиться
Источник
  • 0
    Спасибо :) Я сделал canvas.toDataURL('image/jpeg', 0.9) и идеальный 3069, и он работает очень хорошо !!!!

Другие вопросы

CodeFix
Цитата дня

"Завидую тестировщикам: все хотят с ними дружить."

Эндрю Таненбаум