【问题标题】:How can I get audio stream playing in a tab in chrome extension manifest v3如何在 Chrome 扩展清单 v3 的选项卡中播放音频流
【发布时间】:2022-01-06 20:09:53
【问题描述】:

为了从清单 v2 中的选项卡捕获输出音频流,可以在后台脚本中使用 chrome.tabCapture.capture API 来获取流。但是,在清单 v3 中,tabCapture 已移至前台,并且在后台脚本中不可用。它在内容脚本中都不可用。

在尝试了一些东西之后,我终于可以让tabCapture 在弹出脚本中工作了。但是,在我的用例中,弹出窗口不能长时间保持打开状态,以便捕获流。相反,我偶然发现了tabCapturegetMediaStreamId 方法,它给了我一个streamId。所以,我想出了这个:

chrome.tabs.query({
  active: true,
  currentWindow: true
}, (tabs) => {
  var tab = tabs[0];
  chrome.tabCapture.getMediaStreamId({consumerTabId: tab.id}, (streamId) => {
    chrome.tabs.sendMessage(tab.id, { action: 'streamId', streamId: streamId });
  });
});

popup.js 文件中存在的上述脚本中,在获取streamId 后,我将其发送到内容脚本。我一直坚持如何从这个 streamId 创建一个流,以便可以捕获/记录流。 documentation 提到使用 getUserMedia() 但我在那里并不幸运。这是我可以通过其他 SO 问题的一点帮助提出的(但它不起作用,我收到此错误DOMException: Error starting tab capture):

navigator.mediaDevices.getUserMedia({
  audio: {
    mandatory: {
      chromeMediaSource: 'tab',
      chromeMediaSourceId: streamId
    }
  }
})

如何让 tabCapture 在 manifest v3 中工作,这是我想要找出的。

【问题讨论】:

  • 将扩展 iframe 添加到网页(参见 web_accessible_resources)并捕获其中的音频。
  • 如果网站正在显示一个流并且你想记录它,有一个 API 可以这样做;您也可以克隆流并通过画布渲染它,并根据需要对其进行修改。
  • @BGPHiJACK 不,站点没有显示流。
  • 嗨@wOxxOm,我尝试在iframe 中打开popup.html。但是在调用tabCapture.capture API 的那一刻,我收到这样的错误:Extension has not been invoked for the current page,这很明显,因为 iframe 的 src 是chrome-extension://<extension_runtime_id>/popup.html。您能否提供有关您建议的方式的更多详细信息?
  • 从一开始就在 iframe 中显示您的 UI,以便在相同的上下文中处理点击。初始 UI 可以很小,即只是一个按钮,在内部单击或悬停时自动调整大小。

标签: javascript google-chrome-extension getusermedia chrome-extension-manifest-v3 mediadevices


【解决方案1】:

这是一个在扩展弹出窗口中捕获音频的解决方案,而不是 service worker。

manifest.json

{
    "name": "Audio Share",
    "version": "0.1",
    "manifest_version": 3,
    "permissions": [
        "tabs",
        "activeTab",
        "tabCapture"
    ],
    "host_permissions": [
        "https://*/"
    ],
    "action": {
        "default_popup": "home.html",
        "default_action": "home.js"
    }
}

home.js

function saveToFile(blob, name) {
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    a.href = url;
    a.download = name;
    a.click();
    URL.revokeObjectURL(url);
    a.remove();
}

function captureTabAudio() {
    chrome.tabCapture.capture({audio: true, video: false}, (stream) => {

        // these lines enable the audio to continue playing while capturing
        context = new AudioContext();
        var newStream = context.createMediaStreamSource(stream);
        newStream.connect(context.destination);

        const recorder = new MediaRecorder(stream);
        const chunks = [];
        recorder.ondataavailable = (e) => {
            chunks.push(e.data);
        };
        recorder.onstop = (e) => saveToFile(new Blob(chunks), "test.wav");
        recorder.start();
        setTimeout(() => recorder.stop(), 5000);
    })
}

document.addEventListener('DOMContentLoaded', function () {
    document.getElementById("share-audio-button").addEventListener("click", function ()
        captureTabAudio();
    })
});

home.html

<html>
    <head>
        <script src="home.js"></script>
    </head>

    <body>
        <h1>Audio Share</h1>
        <button id="share-audio-button">Share Audio</button>
    </body>
</html>

【讨论】:

  • 您的代码确实有效,但是您没有提到它只有在弹出窗口保持打开时才有效。这意味着不要在扩展弹出窗口之外点击。
猜你喜欢
  • 2015-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 2022-11-15
相关资源
最近更新 更多