use*_*053 9 google-chrome-extension service-worker
在清单 v2 中,我曾经像这样从后台脚本播放音频
new Audio(url)
Run Code Online (Sandbox Code Playgroud)
但在 manivest v3 中,相同的脚本显示错误
未捕获的引用错误:音频未定义
如何在 Chrome 扩展中从后台脚本(在 v3 中更改为 Service Worker)播放音频?
tsg*_*rgo 18
It's not currently possible to play or capture media directly in service workers because they don't have access to DOM APIs.
Offscreen documents is out for Chrome version 109, so here is my solution based on the api test file from Chromium. Because code on an offscreen document has access to the needed API, you need to open one and use message passing to play the sound from there. This solution is far more elegant than the older one, which utilized a visible popup window for the same reason.
To play a sound in the service worker, call the playSound() function with the appropriate parameters as shown below.
If you don't play sounds for 30 seconds, the offscreen document will be closed automatically because of the "lifetime enforcement".
manifest.json
...
"permissions": ["offscreen"]
...
Run Code Online (Sandbox Code Playgroud)
background.js
/**
* Plays audio files from extension service workers
* @param {string} source - path of the audio file
* @param {number} volume - volume of the playback
*/
async function playSound(source = 'default.wav', volume = 1) {
await createOffscreen();
await chrome.runtime.sendMessage({ play: { source, volume } });
}
// Create the offscreen document if it doesn't already exist
async function createOffscreen() {
if (await chrome.offscreen.hasDocument()) return;
await chrome.offscreen.createDocument({
url: 'offscreen.html',
reasons: ['AUDIO_PLAYBACK'],
justification: 'testing' // details for using the API
});
}
Run Code Online (Sandbox Code Playgroud)
offscreen.html
<script src="offscreen.js"></script>
Run Code Online (Sandbox Code Playgroud)
offscreen.js
// Listen for messages from the extension
chrome.runtime.onMessage.addListener(msg => {
if ('play' in msg) playAudio(msg.play);
});
// Play sound with access to DOM APIs
function playAudio({ source, volume }) {
const audio = new Audio(source);
audio.volume = volume;
audio.play();
}
Run Code Online (Sandbox Code Playgroud)
Note: The offscreen API is relatively new, so some users might not yet have the minimum required version of Chrome (109) to support it. If you care about such users, you could use the older solution as a polyfill by checking if chrome.offscreen is undefined.
One last thing: You should update the justification property for creating the offscreen document. It's required, but not yet used. The documentation says the following:
justification
A developer-provided string that explains, in more detail, the need for the background context. The user agent may use this in display to the user.
As written in the official documentation:
目前无法直接在 Service Worker 中播放或捕获媒体。为了让 Manifest V3 扩展能够利用 Web 的媒体播放和捕获功能,该扩展需要使用 chrome.windows.create() 或 chrome.tabs.create() 创建一个窗口环境。创建后,扩展可以使用消息传递来协调播放文档和 Service Worker 之间的关系。
直到他们对此采取行动之前(希望他们最终会这样做 - 考虑到在他们的文章中使用“当前”),这里有一个快速解决方法:
audio.html
<link href='icon.png' rel='icon' type='image/x-icon'>
<title>Notification</title>
<script src="audio.js"></script>
<style> :root { color-scheme: light dark }</style>
Run Code Online (Sandbox Code Playgroud)
audio.js
resizeTo(0, 0);
onload = () => {
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
let audio = new Audio(urlParams.get('src'));
audio.volume = urlParams.get('volume');
audio.play();
setTimeout(close, urlParams.get('length'));
}
Run Code Online (Sandbox Code Playgroud)
background.js(服务人员)
function playSound() {
let url = chrome.runtime.getURL('audio.html');
// set this string dynamically in your code, this is just an example
// this will play success.wav at half the volume and close the popup after a second
url += '?volume=0.5&src=success.wav&length=1000';
chrome.windows.create({
type: 'popup',
focused: true,
top: 1,
left: 1,
height: 1,
width: 1,
url,
})
}
Run Code Online (Sandbox Code Playgroud)
一旦playSound()被调用,它将创建一个弹出窗口来播放声音。最好将弹出窗口的图标设置为带有标签的扩展程序图标<link>,这样您的用户就会知道弹出窗口的来源。
请注意,audio.js必须从单独的文件链接。否则,您将收到内联脚本策略违规错误。
如果您在使用chrome.notifications API发送 Toast 通知时播放声音,您可能需要将弹出窗口移到通知后面。一个简单的方法是在右下角创建弹出窗口:top: 99999, left: 99999然后在您的 javascript 中:moveTo(window.screenX - 100, window.screenY);
或者,您可以将弹出窗口本身变成 toast 通知。
MV3 的离屏文档功能似乎正在做一些工作。借助这个新的 API,扩展程序将能够打开可访问 DOM API 的有限的屏幕外文档。
然而,这不会是最终的解决方案。正如提案中所述,从长远来看,Chromium 打算直接在扩展服务工作者中支持其中许多功能。
| 归档时间: |
|
| 查看次数: |
4015 次 |
| 最近记录: |