JavaScript获得Audio.setSinkId的权限

时间:2018-02-18 16:51:58

标签: javascript google-chrome audio google-chrome-app

我试图在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' is not available (but actually it should)
- I need a secure connection (but how do I get this at a chrome app?)

1 个答案:

答案 0 :(得分:3)

根据规范,应该有一个Permissions.request()方法,该方法应接受一个 PermissionDescriptor 对象,该对象本身应支持值{strong> "speaker"的{​​{3}} 。

因此,按照规格,这将为我们提供

 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()的Chrome)确实在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 );

PermissionName


Ps:请注意,如果/当浏览器支持规范定义的API时,它甚至可以As a fiddle since Stack-Snippets iframes won't allow for the use of the microphone.be possible