我正在尝试在chrome应用程序的音频元素中更改sinkId

代码:

var audio = new Audio();
audio.setSinkId("communications");

我会收到此错误:
DOMException: No permission to use requested device
因此,为了获得许可,我尝试这样做:

navigator.webkitGetUserMedia({
    audio: true
}, (stream) => {
    console.log("stream: ", stream);
}, (error) => {
    console.log("error: ", error);
});

但是现在我得到了:

error:
NavigatorUserMediaError {name: "InvalidStateError", message: "", constraintName: ""}

我不知道
  • 'audio'不可用(但实际上应该可用)
  • 我需要安全的连接(但是如何在chrome应用程序中获取此连接?)
  • 最佳答案

    2020年
    现在有一个mediacapture-output WG,他们确实定义了MediaDevices接口(interface)的扩展,该接口(interface)添加了一个 selectAudioOutput() 方法来处理内部权限请求。
    此方法将返回一个deviceInfo对象,从中可以提取要传递给deviceIdHTMLMediaElement.setSinkId()

    const deviceInfo = await navigator.mediaDevices.selectAudioOuput();
    audio_elem.setSinkId(deviceInfo.deviceId);
    
    还要注意,关于将此setSinkId方法重命名为setAudioOutput,存在积极的讨论,因此当浏览器将开始实现所有这些功能时,它可能会再次发生变化。

    根据规范,应该有一个 Permissions.request() 方法,该方法应接受PermissionDescriptor对象,该对象本身应支持值PermissionName "speaker"
    因此,按照规范,这将使我们
     await navigator.permissions.request( { name: "speaker" } );
     const all_devices = await navigator.mediaDevices.enumerateDevices();
     const audio_outs = all_devices.filter( ({ kind }) => kind === "audiooutput" );
     // ...
     audioElem.setSinkId( audio_outs[ n ].deviceId );
    

    但是截至2019年12月今天,没有浏览器支持任何一种...
    Chrome浏览器(这是目前唯一支持MediaElement.setSinkId()的一个)确实在Permission.request()下公开了chrome://flags/#enable-experimental-web-platform-features方法,但它们仍不支持PermissionName "speaker"
    因此,我们仍然需要不是最优的解决方法,而是请求"microphone"一个。
    (async () => {
      const query = await navigator.permissions.query( { name: "microphone" } );
      switch( query.state ) {
        case "denied": throw new Error('denied');
        case "prompt":
          await queryUserMedia();
          await getListOfDevices();
          break;
        case "granted": await getListOfDevices();
      }
      function queryUserMedia() {
        return navigator.mediaDevices.getUserMedia( { audio: true } );
      }
      async function getListOfDevices() {
        const all_devs = await navigator.mediaDevices.enumerateDevices();
        const audioouts = all_devs.filter( ({ kind }) => kind === "audiooutput" );
        const options = audioouts.map( ( dev, index ) => {
          const name = dev.label || ('audio out ' + index );
          return new Option( name , dev.deviceId );
        } );
        sel.append.apply( sel, options );
        sel.onchange = e => aud.setSinkId( sel.value );
      }
    
    })().catch( console.error );
    
    As a fiddle since Stack-Snippets iframes won't allow for the use of the microphone.

    Ps:请注意,如果/当浏览器支持规范定义的API时,它甚至会从be possiblerun this code on non-secure contexts

    关于JavaScript获得Audio.setSinkId的权限,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48854159/

    10-12 01:47