如何使用相机
要访问用户的相机(和/或麦克风),我们使用JavaScript MediaStream API。该API允许通过流访问这些设备捕获的视频和音频。
第一步是检查浏览器是否支持此API:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#cc99cd">if</span> <span style="color:#cccccc">(</span>
<span style="color:#7ec699">"mediaDevices"</span> <span style="color:#cc99cd">in</span> navigator <span style="color:#67cdcc">&&</span>
<span style="color:#7ec699">"getUserMedia"</span> <span style="color:#cc99cd">in</span> navigator<span style="color:#cccccc">.</span>mediaDevices
<span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span>
<span style="color:#999999">// ok, browser supports it</span>
<span style="color:#cccccc">}</span></code></span>
在现代浏览器中,支持是不错的(当然没有Internet Explorer)。
捕获视频流
为了捕获由摄像机生成的视频流,我们使用对象的getUserMedia
方法mediaDevices
。
该方法接收一个对象,该对象具有我们请求的媒体类型(视频或音频)以及一些要求。首先,我们可以通过{video: true}
从摄像机获取视频。
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#cc99cd">const</span> videoStream <span style="color:#67cdcc">=</span> <span style="color:#cc99cd">await</span> navigator<span style="color:#cccccc">.</span>mediaDevices<span style="color:#cccccc">.</span><span style="color:#f08d49">getUserMedia</span><span style="color:#cccccc">(</span><span style="color:#cccccc">{</span> video<span style="color:#cccccc">:</span> <span style="color:#f08d49">true</span> <span style="color:#cccccc">}</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span></code></span>
此呼叫将询问用户是否允许访问摄像机。如果用户拒绝,它将引发异常并且不返回流。因此,必须在try / catch块内完成处理这种情况。
请注意,它会返回Promise,因此您必须使用async / await或then
块。
视频要求
我们可以通过传递有关所需分辨率以及最小和最大限制的信息来改善视频的要求:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#cc99cd">const</span> constraints <span style="color:#67cdcc">=</span> <span style="color:#cccccc">{</span>
video<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span>
width<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span>
min<span style="color:#cccccc">:</span> <span style="color:#f08d49">1280</span><span style="color:#cccccc">,</span>
ideal<span style="color:#cccccc">:</span> <span style="color:#f08d49">1920</span><span style="color:#cccccc">,</span>
max<span style="color:#cccccc">:</span> <span style="color:#f08d49">2560</span><span style="color:#cccccc">,</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
height<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span>
min<span style="color:#cccccc">:</span> <span style="color:#f08d49">720</span><span style="color:#cccccc">,</span>
ideal<span style="color:#cccccc">:</span> <span style="color:#f08d49">1080</span><span style="color:#cccccc">,</span>
max<span style="color:#cccccc">:</span> <span style="color:#f08d49">1440</span><span style="color:#cccccc">,</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">;</span>
<span style="color:#cc99cd">const</span> videoStream <span style="color:#67cdcc">=</span> <span style="color:#cc99cd">await</span> navigator<span style="color:#cccccc">.</span>mediaDevices<span style="color:#cccccc">.</span><span style="color:#f08d49">getUserMedia</span><span style="color:#cccccc">(</span>constraints<span style="color:#cccccc">)</span><span style="color:#cccccc">;</span></code></span>
这样,流以正确的宽度和高度比例进入。如果它是处于纵向模式的手机,则需要进行尺寸反转。
在页面上显示视频
好的,既然有了流,我们该如何处理?
我们可以将视频显示在页面上的video
元素中:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#999999">// considering there is a</span>
<span style="color:#999999">// <video autoplay id="video"></video> </span>
<span style="color:#999999">// tag in the page</span>
<span style="color:#cc99cd">const</span> video <span style="color:#67cdcc">=</span> document<span style="color:#cccccc">.</span><span style="color:#f08d49">querySelector</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"#video"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
<span style="color:#cc99cd">const</span> videoStream <span style="color:#67cdcc">=</span> <span style="color:#cc99cd">await</span> navigator<span style="color:#cccccc">.</span>mediaDevices<span style="color:#cccccc">.</span><span style="color:#f08d49">getUserMedia</span><span style="color:#cccccc">(</span>constraints<span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
video<span style="color:#cccccc">.</span>srcObject <span style="color:#67cdcc">=</span> videoStream<span style="color:#cccccc">;</span></code></span>
注意标记中的autoplay
属性video
。没有它,您需要调用video.play()
以实际开始显示图像。
访问手机的前后摄像头
默认情况下getUserMedia
将使用系统的默认视频录制设备。如果手机带有两个摄像头,则使用前置摄像头。
要访问后置摄像头,我们必须facingMode: "environment"
在视频要求中包括:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#cc99cd">const</span> constraints <span style="color:#67cdcc">=</span> <span style="color:#cccccc">{</span>
video<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span>
width<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span> <span style="color:#67cdcc">...</span> <span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
height<span style="color:#cccccc">:</span> <span style="color:#cccccc">{</span> <span style="color:#67cdcc">...</span> <span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
facingMode<span style="color:#cccccc">:</span> <span style="color:#7ec699">"environment"</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">,</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">;</span></code></span>
默认值为facingMode: "user"
,即前置摄像头。
请注意,如果要更改已播放视频的摄像机,则需要先停止当前流,然后再用其他摄像机的流替换它:
<span style="color:#cccccc"><code class="language-javascript">videoStream<span style="color:#cccccc">.</span><span style="color:#f08d49">getTracks</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">.</span><span style="color:#f08d49">forEach</span><span style="color:#cccccc">(</span><span style="color:#cccccc">(</span>track<span style="color:#cccccc">)</span> <span style="color:#67cdcc">=</span><span style="color:#67cdcc">></span> <span style="color:#cccccc">{</span>
track<span style="color:#cccccc">.</span><span style="color:#f08d49">stop</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
<span style="color:#cccccc">}</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span></code></span>
截屏
您可以做的另一件很酷的事情是捕获视频的图像(屏幕快照)。
您可以在画布上绘制当前视频帧,例如:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#999999">// considering there is a</span>
<span style="color:#999999">// <canvas id="canvas"></canvas></span>
<span style="color:#999999">// tag in the page</span>
<span style="color:#cc99cd">const</span> canvas <span style="color:#67cdcc">=</span> document<span style="color:#cccccc">.</span><span style="color:#f08d49">querySelector</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"#canvas"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
canvas<span style="color:#cccccc">.</span>width <span style="color:#67cdcc">=</span> video<span style="color:#cccccc">.</span>videoWidth<span style="color:#cccccc">;</span>
canvas<span style="color:#cccccc">.</span>height <span style="color:#67cdcc">=</span> video<span style="color:#cccccc">.</span>videoHeight<span style="color:#cccccc">;</span>
canvas<span style="color:#cccccc">.</span><span style="color:#f08d49">getContext</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"2d"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">.</span><span style="color:#f08d49">drawImage</span><span style="color:#cccccc">(</span>video<span style="color:#cccccc">,</span> <span style="color:#f08d49">0</span><span style="color:#cccccc">,</span> <span style="color:#f08d49">0</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span></code></span>
您还可以在img
元素中显示画布内容。
在本教程创建的示例中,我添加了一个按钮,该按钮可从画布动态创建图像并将其添加到页面。就像是:
<span style="color:#cccccc"><code class="language-javascript"><span style="color:#cc99cd">const</span> img <span style="color:#67cdcc">=</span> document<span style="color:#cccccc">.</span><span style="color:#f08d49">createElement</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"img"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
img<span style="color:#cccccc">.</span>src <span style="color:#67cdcc">=</span> canvas<span style="color:#cccccc">.</span><span style="color:#f08d49">toDataURL</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"image/png"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">;</span>
screenshotsContainer<span style="color:#cccccc">.</span><span style="color:#f08d49">prepend</span><span style="color:#cccccc">(</span>img<span style="color:#cccccc">)</span><span style="color:#cccccc">;</span></code></span>
结论
完整的源代码在这里:https : //github.com/doug2k1/javascript-camera