65.9K
CodeProject 正在变化。 阅读更多。
Home

在浏览器中使用 Media Capture API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (9投票s)

2015年7月28日

CPOL

6分钟阅读

viewsIcon

20089

今天我想尝试一下由 W3C 的 Web Real-Time Communications Working Group 和 Device APIs Working Group 联合开发的 Media Capture and Streams API。

今天我想尝试一下 Media Capture and Streams API,该 API 由 W3C 的 Web Real-Time Communications Working GroupDevice APIs Working Group 联合开发。一些开发者可能将其简称为 getUserMedia,这是允许网页访问媒体捕获设备(如网络摄像头和麦克风)的主要接口。

您可以在 我的 GitHub 上找到此项目的源代码。 此外,这里有一个可供您试验的可用演示。 在最新的 Windows 10 预览版本中,Microsoft 首次在 Microsoft Edge 浏览器中添加了对媒体捕获 API 的支持。 大部分代码取自 Edge 开发团队在 其测试驱动网站上 制作的 Photo Capture 示例。

对于那些想深入了解的读者,Eric Bidelman 在 HTML5 rocks 上有一篇很棒的文章,其中详细介绍了此 API 的发展历程。

快速上手

要理解 Media Capture APIs,getUserMedia() 方法 是一个很好的起点。getUserMedia() 调用接受 MediaStreamConstraints 作为输入参数,它定义了捕获设备和捕获媒体流的首选项和/或要求,例如相机 facingMode、麦克风音量和视频分辨率。

通过 MediaStreamConstraints,您还可以使用设备的 deviceId 来选择特定的捕获设备,该 deviceId 可以通过 enumerateDevices() 方法获得。一旦用户授予权限,如果满足特定的 MediaStreamConstraintsgetUserMedia() 调用将返回一个带有 MediaSteam 对象的 Promise。

所有这些都无需下载插件!在此示例中,我们将深入研究该 API,并对捕获的视频和图像创建一些不错的滤镜。您的浏览器支持它吗?getUserMedia() 自 Chrome 21、Opera 18 和 Firefox 17 以来就已存在,并且现在 Edge 也支持了。

功能检测

功能检测是检查 navigator.getUserMedia 是否存在的简单方法。在每个浏览器中进行检查是一个庞大的工程,因此我建议您直接使用 Modernizr 来进行检查。它的工作原理如下:

if (Modernizr.getusermedia) {
  var getUM = Modernizr.prefixed('getUserMedia', navigator);
  getUM({video: true}, function( //...
  //...
}

在没有 Modernizr 的情况下,如本示例所示,您必须使用:

	navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
 
if (!navigator.getuserMedia) {
  Console.log('You are using a browser that does not support the Media Capture API');
}

视频播放器

在我们的 HTML 中,您可以在页面顶部找到 video 标签。您会注意到它也设置为自动播放。否则,视频将永久冻结在第一帧。

<div class="view--video">
    <video id="videoTag" src="" autoplay muted class="view--video__video"></video>
</div>

目前还没有设置媒体的源,但我们稍后将通过 JavaScript 注入该源。

访问输入设备

这项新功能可以为开发人员带来许多新的机会,但对于最终用户来说也可能存在安全风险,因此,当您启动此 Web 应用时,首先会注意到的是它请求使用您网络摄像头的权限。getUserMedia 接受几个参数。第一个是指定您要访问的每种媒体的详细信息和要求的对象。要访问网络摄像头,第一个参数应为 {video: true}。另外,要同时使用麦克风和相机,请传递 {video: true, audio: true}。

支持多个网络摄像头

这才是真正有趣的地方。我们还在本示例中使用了 MediaDevices.enumeratedDevices 方法。它收集有关您系统上可用的媒体输入/输出设备的信息,例如麦克风、相机和扬声器。这是一个 Promise,它将返回几个属性,包括设备的 kind(类型),例如 "videoinput""audioinput""audiooutput"。此外,它可以生成一个唯一的字符串 ID,例如 ( videoinput: id = csO9c0YpAf274OuCPUA53CNE0YHlIr2yXCi+SqfBZZ8=),最后还有一个用于描述设备的标签,例如 "FaceTime HD Camera (Built-in)"。但这仍然是一项实验性技术,甚至还没有在 CanIUse.com 上列出。

为视频播放器设置源

initalizeVideoStream 函数中,您可以看到我们正在从页面中获取 video 标签并将其源设置为我们传入的流。Stream 本身是一个 blob。如果浏览器不支持 srcObject 属性,它将回退到从媒体流创建 URL 并设置该 URL。

    // initializeVideoStream() - Callback function when getUserMedia() returns successfully with a mediaStream object
    // 1. Set the mediaStream on the video tag
    // 2. Use 'srcObject' attribute to determine whether to use the standard-based API or the legacy version
 
    var initializeVideoStream = function(stream) {
        mediaStream = stream;
 
        var video = document.getElementById('videoTag');
        if (typeof (video.srcObject) !== 'undefined') {
            video.srcObject = mediaStream;
        }
        else {
            video.src = URL.createObjectURL(mediaStream);
        }
        if (webcamList.length > 1) {
            document.getElementById('switch').disabled = false;
        }
    };

应用 CSS 滤镜

我不太擅长拍照,所以经常依赖 Instagram 为我提供的滤镜。但是,如果您可以为您的视频或静态图像应用自己的滤镜呢?您可以做到!

我为视频流创建了一个简单的函数,允许我实时应用 CSS 滤镜。用于图像的函数几乎相同。

    // changeCssFiltersOnVid() - Cycle through CSS filters applied to the video stream
    // 1. Grab a reference to the video tag
    // 2. Keep the original CSS classes while still adding the filters
    // 3. Loop through all of the filters
 
    var changeCssFilterOnVid = function () {
        var el       = document.getElementById('videoTag');
        el.className = 'view--video__video';
 
        var effect = filters[index++ % filters.length]
        if (effect) {
            el.classList.add(effect);
            console.log(el.classList);
        }
    }

在类的顶部,我有一个滤镜数组可以循环遍历。它们存储为字符串,对应于 CSS 中名称相同的类。// CSS filters var index = 0; var filters = ['grayscale', 'sepia', 'blur', 'invert', 'brightness', 'contrast', '']; 以及 CSS 中的

/* image * video filters */
.grayscale {
    -webkit-filter: grayscale(1);
    -moz-filter: grayscale(1);
    -ms-filter: grayscale(1);
    filter: grayscale(1);
}
 
.sepia {
    -webkit-filter: sepia(1);
    -moz-filter: sepia(1);
    -ms-filter: sepia(1);
    filter: sepia(1);
}
 
.blur {
    -webkit-filter: blur(3px);
    -moz-filter: blur(3px);
    -ms-filter: blur(3px);
    filter: blur(3px);
}

您可以在 Edge 测试驱动页面上查看更多工作示例,并实时更改值。

保存图像

深入研究代码,您可能会看到一些您不熟悉的功能。最先引起我注意的是 navigator.msSaveBlobBlob 构造函数允许您直接在客户端轻松创建和操作 blob(本质上是一个文件)。它在 IE 10+ 中受支持。

msSaveBlob 允许您将此 blob 对象(在本例中为我们的快照图像)保存到磁盘。它还有一个同名方法 msSaveOrOpenBlob,它也允许您从浏览器中打开图像。

 // savePhoto() - Function invoked when user clicks on the canvas element
 // 1. If msSaveBlob is supported, get the photo blob from the canvas and save the image file
 // 2. Otherwise, set up the download attribute of the anchor element and download the image file
 
    var savePhoto = function() {
        if (photoReady) {
            var canvas = document.getElementById('canvasTag');
            if (navigator.msSaveBlob) {
                var imgData = canvas.msToBlob('image/jpeg');
                navigator.msSaveBlob(imgData, 'myPhoto.jpg');
            }
            else {
                var imgData = canvas.toDataURL('image/jpeg');
                var link    = document.getElementById('saveImg');
                link.href   = imgData;
                link.download = 'myPhoto.jpg';
                link.click();
            }
            canvas.removeEventListener('click', savePhoto);
            document.getElementById('photoViewText').innerHTML = '';
            photoReady = false;
        }
    };

如果浏览器支持该方法,它将减少我们需要编写的代码量来保存图像。

我们还可以去哪里?

这仅仅是开始。我们还可以利用 WebGL,它可以实现更多滤镜,以及在高度交互式环境内构建实时视频/音频流。也许那将是我的下一个项目……

此外,您还可以连接到 Web Audio API 来对音频输出应用频率调制。来自 Web Audio tuner 的此示例很好地说明了这一点。有些人更喜欢视觉学习,所以也请查看这个 Microsoft 示例。

最后,随着移动浏览器不断采用更多这项技术,您将能够使用这些 JavaScript API 来连接底层硬件,并使其在移动设备上运行,无论平台如何。现在是成为一名 Web 开发者的绝佳时机,希望在使用完本文后,您就能理解我为什么如此兴奋能参与其中。

源代码: https://github.com/DaveVoyles/GetUserMedia-sample

可用示例: http://getusermedia.azurewebsites.net/

更多关于 JavaScript 的实践

Microsoft 提供了大量关于各种开源 JavaScript 主题的免费学习资源,并且我们正致力于通过 Microsoft Edge 创造更多内容。以下是一些值得查看的资源:

以及一些免费的入门工具:Visual Studio CodeAzure 试用版跨浏览器测试工具 – 所有这些都可在 Mac、Linux 或 Windows 上使用。

本文是 Microsoft Web 开发技术系列的一部分。我们很高兴与您分享 Microsoft Edge 和新的 EdgeHTML 渲染引擎。通过 http://dev.modern.ie/ 获取免费虚拟机或在您的 Mac、iOS、Android 或 Windows 设备上远程测试。

© . All rights reserved.