如何开发带Popup弹窗与点击触发侧边栏的Chrome录屏扩展
Chrome录屏扩展实现方案(含侧边栏注入)
核心文件分工
popup.html:提供扩展的点击入口(开始录制按钮),仅在点击扩展图标时显示。content-script.js:负责向当前页面DOM注入侧边栏UI,处理侧边栏的交互逻辑。background.js:管理录屏的核心逻辑(启动、暂停、停止录制),作为popup和content script的通信中转。manifest.json:扩展的配置文件,声明权限、文件引用等。
1. manifest.json 配置
需要声明必要权限,同时指定各个文件的作用范围:
{ "manifest_version": 3, "name": "屏幕录制侧边栏", "version": "1.0", "permissions": ["activeTab", "scripting", "storage", "desktopCapture"], "action": { "default_popup": "popup.html" }, "background": { "service_worker": "background.js" }, "content_scripts": [ { "matches": ["<all_urls>"], "js": ["content-script.js"] } ] }
2. popup.html 实现
仅保留开始录制按钮,点击后触发后台指令:
<!DOCTYPE html> <html> <head> <style> body { width: 150px; padding: 10px; } button { width: 100%; padding: 8px; cursor: pointer; } </style> </head> <body> <button id="startRecord">开始录制</button> <script src="popup.js"></script> </body> </html>
配套的popup.js:
document.getElementById('startRecord').addEventListener('click', async () => { const [tab] = await chrome.tabs.query({ active: true, currentWindow: true }); chrome.runtime.sendMessage({ type: 'START_RECORD', tabId: tab.id }); window.close(); });
3. content-script.js 实现
负责注入侧边栏DOM,处理计时器、暂停/停止按钮交互:
const sidebarHTML = ` <div id="record-sidebar" style="position: fixed; right: 0; top: 0; width: 250px; height: 100vh; background: #fff; box-shadow: -2px 0 5px rgba(0,0,0,0.2); z-index: 999999; padding: 20px; box-sizing: border-box;"> <h3>正在录制</h3> <div id="timer" style="font-size: 24px; margin: 20px 0; text-align: center;">00:00:00</div> <button id="pauseBtn" style="width: 100%; padding: 10px; margin-bottom: 10px; background: #f39c12; color: white; border: none; border-radius: 4px; cursor: pointer;">暂停</button> <button id="stopBtn" style="width: 100%; padding: 10px; background: #e74c3c; color: white; border: none; border-radius: 4px; cursor: pointer;">停止</button> </div> `; let timerInterval; let seconds = 0; chrome.runtime.onMessage.addListener((message) => { switch(message.type) { case 'SHOW_SIDEBAR': injectSidebar(); startTimer(); break; case 'PAUSE_RECORD': togglePause(); break; case 'STOP_RECORD': stopRecording(); break; } }); function injectSidebar() { if (!document.getElementById('record-sidebar')) { document.body.insertAdjacentHTML('beforeend', sidebarHTML); document.getElementById('pauseBtn').addEventListener('click', () => { chrome.runtime.sendMessage({ type: 'PAUSE_RECORD' }); }); document.getElementById('stopBtn').addEventListener('click', () => { chrome.runtime.sendMessage({ type: 'STOP_RECORD' }); }); } } function startTimer() { timerInterval = setInterval(() => { seconds++; const hours = Math.floor(seconds / 3600).toString().padStart(2, '0'); const minutes = Math.floor((seconds % 3600) / 60).toString().padStart(2, '0'); const secs = (seconds % 60).toString().padStart(2, '0'); document.getElementById('timer').textContent = `${hours}:${minutes}:${secs}`; }, 1000); } function togglePause() { const pauseBtn = document.getElementById('pauseBtn'); if (timerInterval) { clearInterval(timerInterval); timerInterval = null; pauseBtn.textContent = '继续'; } else { startTimer(); pauseBtn.textContent = '暂停'; } } function stopRecording() { if (timerInterval) clearInterval(timerInterval); const sidebar = document.getElementById('record-sidebar'); if (sidebar) sidebar.remove(); seconds = 0; }
4. background.js 实现
处理录屏核心逻辑,以及消息中转:
let mediaRecorder; let recordedChunks = []; let currentTabId; chrome.runtime.onMessage.addListener(async (message) => { switch(message.type) { case 'START_RECORD': currentTabId = message.tabId; const streamId = await chrome.desktopCapture.chooseDesktopMedia(['screen', 'window'], null); if (streamId) { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: streamId } } }); mediaRecorder = new MediaRecorder(stream); mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) recordedChunks.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(recordedChunks, { type: 'video/webm' }); const url = URL.createObjectURL(blob); chrome.downloads.download({ url: url, filename: '录制视频.webm' }); recordedChunks = []; }; mediaRecorder.start(); chrome.tabs.sendMessage(currentTabId, { type: 'SHOW_SIDEBAR' }); } break; case 'PAUSE_RECORD': if (mediaRecorder) { mediaRecorder.state === 'recording' ? mediaRecorder.pause() : mediaRecorder.resume(); } break; case 'STOP_RECORD': if (mediaRecorder && mediaRecorder.state !== 'inactive') { mediaRecorder.stop(); mediaRecorder.stream.getTracks().forEach(track => track.stop()); } chrome.tabs.sendMessage(currentTabId, { type: 'STOP_RECORD' }); break; } });
关键逻辑说明
- 通信机制:通过
chrome.runtime.sendMessage和chrome.tabs.sendMessage实现三者间消息传递。 - 侧边栏注入:content script直接操作页面DOM,插入固定定位的侧边栏,确保层级最高不被遮挡。
- 录屏核心:用
desktopCaptureAPI获取屏幕权限,通过MediaRecorder处理视频录制与文件生成。
内容的提问来源于stack exchange,提问作者Fatma
相关产品推荐
相关产品推荐

