在使用 navigate.getUserMedia() 时选择相机

Posted

技术标签:

【中文标题】在使用 navigate.getUserMedia() 时选择相机【英文标题】:Select the camera while using navigate.getUserMedia() 【发布时间】:2013-05-24 07:33:06 【问题描述】:

我正在使用 navigate.getUserMedia() 方法在我的手机上捕获视频并对其进行进一步处理。但截至目前,它正在使用前置摄像头捕捉视频。如何让它访问后置摄像头??

以下是我在应用程序中使用的一些示例代码:

  navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
  if (navigator.getUserMedia)
    navigator.getUserMedia(video: true, successCallback, errorCallback);

提前致谢

【问题讨论】:

我觉得这个问题太笼统了,可能取决于设备的供应商、软件和型号。 但是这段代码在各种平台上运行,..问题是它访问前置摄像头,所以我们可能有一些方法可以指定它访问后置摄像头,..或者弹出一个可用的相机并让用户从中选择.. 【参考方案1】:

simpl.info 上的这个示例演示了如何使用 MediaStreamTrack.getSources 从多个视频源中进行选择。

https://simpl.info/getusermedia/sources/

我可以确认这在 Chrome 32 中有效。

【讨论】:

这应该是正确的答案。虽然没有在所有设备上实现,但我可以确认它可以在 android 上的 chrome 中运行,而不是在我的 gs2 上的常规浏览器中(我知道它是旧的)。在 ios7 中不起作用,但我将在周一到达办公室后立即在 ios8 beta 3 上进行测试。 好吧,它并没有解决我的问题,因为它不适用于 iOS Safari。两个摄像头都激活了我的前置摄像头【参考方案2】:

您可以使用facingMode 分别为前置或后置摄像头选择“用户”或“环境”。不确定浏览器是否支持,但它适用于 Android Chrome 58。

使用

navigator.getUserMedia(video:  facingMode:  exact: "environment"   ,
successCallback, errorCallback);

或者,允许回退到其他相机

navigator.getUserMedia(video:  facingMode: "environment"  ,
successCallback, errorCallback);

而不是

navigator.getUserMedia(video: true, successCallback, errorCallback);

来自https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

【讨论】:

感谢这个答案!但是它会在跨平台上工作吗【参考方案3】:
//----------------------------------------------------------------------
//  Here we list all media devices, in order to choose between
//  the front and the back camera.
//      videoDevices[0] : Front Camera
//      videoDevices[1] : Back Camera
//  I used an array to save the devices ID 
//  which i get using devices.forEach()
//  Then set the video resolution.
//----------------------------------------------------------------------
navigator.mediaDevices.enumerateDevices()
.then(devices => 
    var videoDevices = [0,0];
    var videoDeviceIndex = 0;
    devices.forEach(function(device) 
    console.log(device.kind + ": " + device.label +
        " id = " + device.deviceId);
    if (device.kind == "videoinput")   
        videoDevices[videoDeviceIndex++] =  device.deviceId;    
    
    );


    var constraints =  width:  min: 1024, ideal: 1280, max: 1920 ,
    height:  min: 776, ideal: 720, max: 1080 ,
    deviceId:  exact: videoDevices[1]   
;
return navigator.mediaDevices.getUserMedia( video: constraints );

)
.then(stream => 
    if (window.webkitURL) 
    video.src = window.webkitURL.createObjectURL(stream);
    localMediaStream = stream;
     else if (video.mozSrcObject !== undefined) 
    video.mozSrcObject = stream;
     else if (video.srcObject !== undefined) 
    video.srcObject = stream;
     else 
    video.src = stream;
    )
.catch(e => console.error(e));

【讨论】:

如果您在那里描述您的代码,这将是一个更好的答案! 我将在这里解释一些行。 videoDevices : 是一个简单的数组,其中将包含 frond 和后置摄像头的 iddevices.forEach :将列出所有媒体设备(视频和音频)。如果一个device.kind == "videoinput",表示它是一个视频媒体设备,我们将所有视频设备的ID保存在前面的数组videoDevices中。 var constraints 包含视频分辨率和我们想要启动的相机。 videoDevices[1] = 后置摄像头videoDevices[0] = 前置摄像头。然后我们将约束传递给 getUSerMedia 函数。【参考方案4】:

有关更多信息,请参阅this。

使用哪个摄像头留给设备:“用户代理是 鼓励默认使用用户的主要或系统默认值 摄像头和/或麦克风(视情况而定)以生成媒体 流。”

您可能想问的问题是如何更改默认摄像头。但正如我在评论部分提到的,这会根据所使用的设备操作系统、供应商甚至型号而有所不同,这可能是一个大问题。

编辑(根据后面的改进接受的答案):

请参阅此博客了解如何更改摄像头来源:

https://www.html5rocks.com/en/tutorials/getusermedia/intro/

【讨论】:

【参考方案5】:

长话短说: 如果您想在 OLD 设备上选择不支持 facesMode 约束的后置摄像头 - 您需要在视频中使用 sourceId: exact: device.id 约束: config.

长:

export interface SourceInfo 
  facing: string; // "environment"
  id: string; // "bcb8d32aebb99fdf1d5f2fdb4ec4ec28a381b83f5e3c96cbcb30c4ab757380da"
  kind: string; // "video"
  label: string; // ""

代码(打字稿):

(navigator as any).getUserMedia =
      (navigator as any).getUserMedia ||
      (navigator as any).webkitGetUserMedia ||
      (navigator as any).mozGetUserMedia ||
      (navigator as any).msGetUserMedia;

if (navigator.getUserMedia && (window as any).MediaStreamTrack) 
      (MediaStreamTrack as any).getSources((sources: SourceInfo[]) => 

    this.videoSources = sources.filter((source: SourceInfo) => 
      return source.kind === 'video';
      // or source.facing === 'environment'
    );
    // console.log('got video sources', this.videoSources);

    try 
      const rearCameraDevice = this.videoSources.find((device: SourceInfo) => device.facing === 'environment');
      const anyCameraDevice = this.videoSources[0];
      const constraints = 
        video: 
          mandatory: 
            sourceId: rearCameraDevice.id || anyCameraDevice.id
          
          // these both not work with old constraints...it's new syntax
          // deviceId: this.videoSources[0].id
          // deviceId:  exact: this.videoSources[0].id 
        
      ;
      navigator.getUserMedia(
        <any>constraints, 
        this.successOldStream.bind(this), 
        this.errorOldStream.bind(this)
      );
     catch (error) 
      console.error(error);
    

);
 else 
  console.error('your browser not supported camera/media capturing')

【讨论】:

以上是关于在使用 navigate.getUserMedia() 时选择相机的主要内容,如果未能解决你的问题,请参考以下文章

在哪里使用 CORBA 以及在哪里使用 SNMP 进行监控?

为啥在使用 unicode 时我不能在 :before :after 内容之后使用空格

在哪里使用 callable 以及在哪里使用 Runnable Interface?

在 Observable RxSwift 中使用 'asPromise()' 可以在 PromiseKit Promise 中使用吗?

可以在 SELECT 查询中使用 IF() 但不能在 UPDATE 中使用

使用 React,在使用 react-transition-group 时,在 StrictMode 中不推荐使用 findDOMNode 作为警告