google chrome - JavaScript get permission for Audio.setSinkId - Stack Overflow

I'm trying to change the sinkId at an Audio-Element in a chrome app.Code:var audio = new Audio();

I'm trying to change the sinkId at an Audio-Element in a chrome app.

Code:

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

I'll get this error:

DOMException: No permission to use requested device

So to get the permission I tried to do that:

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

But now I get this:

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

I don't know, whether

  • 'audio' is not available (but actually it should)
  • I need a secure connection (but how do I get this at a chrome app?)

I'm trying to change the sinkId at an Audio-Element in a chrome app.

Code:

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

I'll get this error:

DOMException: No permission to use requested device

So to get the permission I tried to do that:

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

But now I get this:

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

I don't know, whether

  • 'audio' is not available (but actually it should)
  • I need a secure connection (but how do I get this at a chrome app?)
Share Improve this question edited Dec 10, 2019 at 5:30 Kaiido 138k14 gold badges259 silver badges324 bronze badges asked Feb 18, 2018 at 16:51 GerritGerrit 4735 silver badges13 bronze badges 3
  • I have the same problem and looked at the docs: developers.google./web/updates/2015/10/media-devices the example (which is also not working on Windows 10): webrtc.github.io/samples/src/content/devices/input-output And an open issue at github: github./WebAudio/web-audio-api/issues/445 It seems to be broken currently.. PS: There is also an Chrome extension which should be able to switch audio outputs here: chrome.google./webstore/detail/audiopick/… It might contains some interesting code? (haven't looked at it) – Wezelkrozum Commented Feb 19, 2018 at 0:42
  • 1 Thanks for your reply. Unfortunately, the example and the chrome extension aren't working on my puter (Windows 8, chrome version 63.0.3239.132), too. Hope it will be fixed soon! – Gerrit Commented Feb 19, 2018 at 13:56
  • 1 No "invalid state" error here on Chrome v78, but it's still seemingly broken to have to request an audio input stream to get permissions for audio output. I added a bounty to your question to hopefully get a better answer. – Brad Commented Dec 10, 2019 at 4:19
Add a ment  | 

1 Answer 1

Reset to default 7 +200

There is now a mediacapture-output WG and they did define an extension to the MediaDevices interface which adds a selectAudioOutput() method which takes care of the internal permission requests.
This method would return a deviceInfo object from where you can extract the deviceId you would pass to HTMLMediaElement.setSinkId().

const deviceInfo = await navigator.mediaDevices.selectAudioOuput();
audio_elem.setSinkId(deviceInfo.deviceId);

Note also that there is active discussions about renaming this setSinkId method to setAudioOutput, so it might change again when browsers will start implementing all this.

Firefox 93 starts exposing this method, under the media.setsinkid.enabled flag.



Alternatively there should be a Permissions.request() method, which should accept a PermissionDescriptor object which itself should support a PermissionName of value "speaker-selection".

So that would give us

 await navigator.permissions.request( { name: "speaker-selection" } );
 const all_devices = await navigator.mediaDevices.enumerateDevices();
 const audio_outs = all_devices.filter( ({ kind }) => kind === "audiooutput" );
 // ...
 audioElem.setSinkId( audio_outs[ n ].deviceId );


But as of today August of 2021, it seems that still no browser supports this.

Chrome (which is the only one currently supporting MediaElement.setSinkId()) does expose the Permission.request() method under chrome://flags/#enable-experimental-web-platform-features, but they still don't support the PermissionName "speaker-selection" yet.

So we still need the less than optimal workaround of requesting for the "microphone" one instead.

(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: Note that if/when browsers were supporting the specs defined API, then it would even be possible to run this code on non-secure contexts.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744109508a4558885.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信