You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Manifest V3版Chrome屏幕录制扩展关闭弹窗后后台持续录屏实现咨询

Chrome扩展后台录屏需求

我正在开发一款可实现屏幕/标签页录制功能的Chrome扩展。

现有代码

manifest.json

{
  "name": "My Recorer",
  "version": "1.0",
  "manifest_version": 3,
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  },
  "permissions": ["activeTab", "declarativeContent", "storage","tabs", "desktopCapture"]
}

background.js

chrome.runtime.onInstalled.addListener(function (tab) {
  console.log(tab)
})
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div>
    <button style="width: 100%; margin: 5%;" id="start">Record</button>
    <button style="width: 100%; margin: 5%" id="stop">stop</button>
  </div>
  <script src="popup.js"></script>
</body>
</html>
let start = document.getElementById('start'),
    stop  = document.getElementById('stop'),
    mediaRecorder;

start.addEventListener('click', async function(){
    console.log("Start")
    let stream = await recordScreen();
    let mimeType = 'video/webm';
    mediaRecorder = createRecorder(stream, mimeType);
  let node = document.createElement("p");
    node.textContent = "Started recording";
    document.body.appendChild(node);
})

stop.addEventListener('click', function(){
    mediaRecorder.stop();
    let node = document.createElement("p");
    node.textContent = "Stopped recording";
    document.body.appendChild(node);
})

async function recordScreen() {
    return await navigator.mediaDevices.getDisplayMedia({
        audio: true, 
        video: { mediaSource: "screen"}
    });
}

存在问题

当前扩展的录屏功能可正常运行,但关闭扩展弹窗后,录屏进程会直接终止,已录制的内容也会丢失。需要实现扩展弹窗不可见后仍保持录屏正常运行的后台录屏效果,预期实现效果参考下图:
预期效果参考图

解决方案

出现该问题的原因是Chrome扩展的popup页面属于临时上下文,关闭后页面会被直接销毁,运行在popup里的录屏逻辑、MediaRecorder实例都会同步被回收。Manifest V3版本可通过offscreenAPI创建常驻后台的离屏页面承载录屏逻辑,实现步骤如下:

  1. 修改manifest.json,新增offscreen权限:
// 其余配置保持不变,仅更新permissions字段
"permissions": ["activeTab", "declarativeContent", "storage","tabs", "desktopCapture", "offscreen"]
  1. 新建离屏页面文件offscreen.html:
<!DOCTYPE html>
<html>
<body>
<script src="offscreen.js"></script>
</body>
</html>
  1. 新建离屏逻辑文件offscreen.js,承载核心录屏代码:
let mediaRecorder;
const recordedChunks = [];

// 监听来自后台的消息
chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
  if (message.type === 'start-recording') {
    const stream = await navigator.mediaDevices.getDisplayMedia({
      audio: true, 
      video: { mediaSource: "screen"}
    });
    const mimeType = 'video/webm';
    mediaRecorder = new MediaRecorder(stream, { mimeType });
    
    mediaRecorder.ondataavailable = (e) => {
      if (e.data.size > 0) recordedChunks.push(e.data);
    };

    mediaRecorder.onstop = () => {
      const blob = new Blob(recordedChunks, { type: mimeType });
      const url = URL.createObjectURL(blob);
      // 自动下载录制好的视频
      const a = document.createElement('a');
      a.href = url;
      a.download = `recording_${Date.now()}.webm`;
      a.click();
      URL.revokeObjectURL(url);
      recordedChunks.length = 0;
    };

    mediaRecorder.start();
  } else if (message.type === 'stop-recording') {
    if (mediaRecorder?.state === 'recording') {
      mediaRecorder.stop();
      mediaRecorder.stream.getTracks().forEach(track => track.stop());
    }
  }
});
  1. 修改background.js,负责创建离屏页面和转发消息:
async function ensureOffscreenDocument() {
  const existingContexts = await chrome.runtime.getContexts({
    contextTypes: [chrome.runtime.ContextType.OFFSCREEN_DOCUMENT]
  });
  if (existingContexts.length > 0) return;
  await chrome.offscreen.createDocument({
    url: 'offscreen.html',
    reasons: [chrome.offscreen.Reason.USER_MEDIA],
    justification: '用于后台录制屏幕内容'
  });
}

chrome.runtime.onMessage.addListener(async (message, sender, sendResponse) => {
  if (message.type === 'start-recording' || message.type === 'stop-recording') {
    await ensureOffscreenDocument();
    chrome.runtime.sendMessage(message);
  }
});
  1. 修改popup.js,仅保留按钮交互和消息发送逻辑:
const start = document.getElementById('start');
const stop  = document.getElementById('stop');

start.addEventListener('click', async () => {
  await chrome.runtime.sendMessage({ type: 'start-recording' });
  const node = document.createElement("p");
  node.textContent = "已开始录制";
  document.body.appendChild(node);
});

stop.addEventListener('click', async () => {
  await chrome.runtime.sendMessage({ type: 'stop-recording' });
  const node = document.createElement("p");
  node.textContent = "已停止录制,视频将自动下载";
  document.body.appendChild(node);
});

修改后录屏逻辑运行在常驻的离屏页面中,关闭popup不会影响录制进程,停止录制后会自动下载录制好的视频文件。

内容的提问来源于stack exchange,提问作者GMAC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:21:03