JavaScript 获得 Audio.setSinkId 的权限

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

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

代码:

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: ""}

不知道是不是
  • “音频”不可用(但实际上应该)
  • 我需要一个安全的连接(但我如何在 chrome 应用程序中获得它?)
  • 最佳答案

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

    const deviceInfo = await navigator.mediaDevices.selectAudioOuput();
    audio_elem.setSinkId(deviceInfo.deviceId);
    
    另请注意,关于重命名此 setSinkId 的讨论非常活跃。方法 setAudioOutput ,所以当浏览器开始实现这一切时,它可能会再次改变。
    Firefox 93 开始公开此方法,位于 media.setsinkid.enabled 下。旗帜。

    或者应该有一个 Permissions.request() 方法,它应该接受一个 PermissionDescriptor 对象,该对象本身应该支持 PermissionName值(value) "speaker-selection" .
    所以这会给我们
     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 );
    

    但截至 2021 年 8 月的今天,似乎仍然没有浏览器支持这一点。
    Chrome(这是目前唯一支持 MediaElement.setSinkId() 的)确实暴露了 Permission.request() chrome://flags/#enable-experimental-web-platform-features下的方法,但他们仍然不支持 PermissionName "speaker-selection"然而。
    所以我们仍然需要请求 "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/

    相关文章:

    css - 尽管都由 -webkit 控制,但在 chrome 和 safari 中对等高列使用线性渐变颜色停止呈现不同?

    javascript - 如果我们导航到其他页面,为什么在 React js 中显示用于 seo 的 index.html 标签?

    javascript - 如何在 sourcemaps 中使用断点 (Chrome DevTools)

    javascript - 如何在各种浏览器(如 IE8 和更早版本)中测试我的网页?

    css - 背景大小转换在 chrome 中停止工作

    c# - 在Windows调音台中读取音量值

    java - 如果我知道音频文件的确切格式并需要重复播放,该如何在Java中播放声音?

    c++ - 架构 armv7s : iPhoneExtAudioFileConvertTest 的 undefined symbol

    javascript - 如何在个人资料图像标签中应用 onchange 图像预览

    java - 使用 GWT ScriptInjector 加载脚本时如何设置 CacheHeaders?