iphone - 来自网络摄像头的 WebRTC 快照并将其保存到 PHP 中的服务器:iPhone Safari 在分辨率高于 2096 时崩溃
问题描述
我有一个工作代码可以从网络摄像头拍摄快照并通过 ajax 将其保存在 PHP 中......但是当我尝试使用高于 2000 的分辨率时,iPhone 上的 safari mobile 崩溃,为什么以及如何解决这个问题?
在这里,如果我这样做getUserMedia({ video:{width: { ideal: 2096
=> 没关系
但是如果我 fo 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.'" />';
?>
******* 问题是:为什么大分辨率会导致 safari mobile 崩溃?
解决方案
您可以.toDataURL()
将那个巨大的图像编码为无损 .png 文件。这可能会生成一个您尝试发布的数兆字节字符串。Safari 可能会在分配或垃圾收集时耗尽连续的 RAM和 gack。您的 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 宽度,如果您让.getUserMedia()
选择它想要的任何高度,您可能会得到 4K 高度;它遵循默认的纵横比。
最后,在实际意义上,分辨率如此之高的图像通常必须在使用之前进行下采样。较低分辨率的 JPEG 图像通常可以满足实际需求。因此,只需捕获较低分辨率的图像。(如果您是一名摄影师,拍摄照片以在光面杂志上打印,那么您已经知道 iPhone 相机的局限性。)
推荐阅读
- ssl-certificate - 远程桌面 SSL Nessus 漏洞 2008R2
- django - 如何将存储在 models.py 中的密钥与从 POST 请求中获取的密钥进行比较?
- asp.net-core - 无法加载嵌入文件清单“Microsoft.Extensions.FileProviders.Embedded.Manifest.xml”ASP.NET Core 3.0
- json - 在 Jmeter 中提取值
- python - Spyder 不再排队命令
- angular - 为什么使用 ng build 时 webpack:// 没有出现在 chrome 中
- c# - 如何仅复制一行并将其粘贴到该表中
- python - 3D 绘图:x 轴上的平滑绘图
- javascript - 为什么这个 JS 函数不能正确导入到我的 Blade.php 中?
- c# - 如何在按钮单击时附加文件、清除表单、加载文件和更新列表视图?