我们从零开始的、详细的、分步的教程,来创建一个基础的录屏插件。这个插件将能够:
点击浏览器工具栏的图标,弹出一个小窗口。
在小窗口中点击“开始录制”按钮,触发浏览器原生屏幕选择界面。
用户选择要录制的屏幕、窗口或标签页后,开始录制。
点击“停止录制”按钮,结束录制。
生成一个可下载的视频文件(通常是 .webm 格式)。
我们将使用 Manifest V3,这是当前 Chrome 扩展的最新标准。
第一步:创建项目结构
首先,在你的电脑上创建一个新的文件夹,比如 screen-recorder-extension。然后在这个文件夹里,创建以下文件和目录

icons/: 你可以先用任意图片作为占位符,或者从网上找一些免费图标。这些图标会显示在浏览器工具栏和扩展管理页面。
第二步:编写 manifest.json (清单文件)
这是扩展的核心配置文件,它告诉 Chrome 关于这个插件的所有信息,包括名称、权限、脚本等。manifest.json
{
"manifest_version": 3,
"name": "简易录屏插件",
"version": "1.0",
"description": "一个简单的Chrome录屏插件,使用 getDisplayMedia API。",
"permissions": [
"storage"
],
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}关键点解释:"manifest_version": 3: 声明我们使用 Manifest V3。
"permissions": ["storage"]: 我们请求 storage 权限,用来在不同脚本之间(比如 popup 和 background)同步录制状态。
"background": { "service_worker": "background.js" }: 指定 background.js 作为我们的 Service Worker。在 V3 中,后台脚本在需要时运行,而不是持续存在,这对于处理录制这种需要持久状态的任务至关重要。
"action": { ... }: 定义了用户在浏览器工具栏上看到和交互的内容。点击图标时,会弹出 popup.html。
第三步:创建用户界面 (popup.html 和 popup.js)
这是用户直接交互的部分。
popup.html
<!DOCTYPE html>
<html>
<head>
<title>录屏插件</title>
<style>
body { width: 200px; font-family: sans-serif; text-align: center; }
button { width: 120px; margin: 5px; padding: 10px; }
#status { font-weight: bold; margin: 10px 0; }
#downloadLink { display: none; }
</style>
</head>
<body>
<h3>简易录屏</h3>
<p id="status">空闲</p>
<button id="startBtn">开始录制</button>
<button id="stopBtn" disabled>停止录制</button>
<a id="downloadLink" download="recording.webm">下载视频</a>
</body>
<script src="popup.js"></script>
</html>popup.js这个脚本负责处理 popup.html 中的按钮点击事件,并与后台脚本 background.js 通信。
const startBtn = document.getElementById('startBtn');
const stopBtn = document.getElementById('stopBtn');
const status = document.getElementById('status');
const downloadLink = document.getElementById('downloadLink');
// 更新UI状态
function updateUI(isRecording, videoUrl = null) {
startBtn.disabled = isRecording;
stopBtn.disabled = !isRecording;
status.textContent = isRecording ? '正在录制...' : '空闲';
if (videoUrl) {
downloadLink.href = videoUrl;
downloadLink.style.display = 'block';
status.textContent = '录制完成!';
} else {
downloadLink.style.display = 'none';
}
}
// 监听开始按钮点击
startBtn.addEventListener('click', () => {
// 向 background.js 发送消息,请求开始录制
chrome.runtime.sendMessage({ type: 'START_RECORDING' }, (response) => {
if (response && response.success) {
updateUI(true);
} else {
console.error("无法开始录制:", response.error);
status.textContent = '错误:无法开始';
}
});
});
// 监听停止按钮点击
stopBtn.addEventListener('click', () => {
// 向 background.js 发送消息,请求停止录制
chrome.runtime.sendMessage({ type: 'STOP_RECORDING' });
});
// 监听来自 background.js 的消息,例如录制已停止
chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'RECORDING_STOPPED') {
updateUI(false, message.url);
}
});
// 当 popup 打开时,检查当前录制状态
chrome.storage.local.get(['isRecording', 'videoUrl'], (result) => {
updateUI(result.isRecording, result.videoUrl);
});第四步:编写核心逻辑 (background.js)这是插件的大脑,它在后台运行,处理实际的屏幕捕获和录制工作。background.js
let mediaRecorder;
let recordedChunks = [];
let stream;
// 监听来自 popup.js 的消息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'START_RECORDING') {
startRecording().then(() => {
sendResponse({ success: true });
}).catch(err => {
sendResponse({ success: false, error: err.message });
});
return true; // 表示我们将异步发送响应
} else if (request.type === 'STOP_RECORDING') {
stopRecording();
sendResponse({ success: true });
}
});
async function startRecording() {
try {
// 1. 获取屏幕捕捉的 MediaStream
stream = await navigator.mediaDevices.getDisplayMedia({
video: { mediaSource: 'screen' },
audio: true // 如果需要录制系统或麦克风声音
});
// 2. 创建 MediaRecorder 实例
mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm' });
// 3. 清空之前的数据块
recordedChunks = [];
// 4. 监听 dataavailable 事件,收集数据块
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
recordedChunks.push(event.data);
}
};
// 5. 监听 stop 事件,当录制停止时处理数据
mediaRecorder.onstop = () => {
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
// 将录制状态和视频URL存入storage
chrome.storage.local.set({ isRecording: false, videoUrl: url });
// 向 popup 发送消息,通知录制已停止并附上URL
chrome.runtime.sendMessage({ type: 'RECORDING_STOPPED', url: url });
// 你也可以选择直接打开下载页面
// chrome.tabs.create({ url: url });
};
// 6. 开始录制
mediaRecorder.start();
// 7. 更新状态
await chrome.storage.local.set({ isRecording: true, videoUrl: null });
// 当用户手动停止屏幕共享时(例如点击浏览器自带的停止共享按钮)
stream.getVideoTracks()[0].onended = () => {
stopRecording();
};
} catch (error) {
console.error('Error starting recording:', error);
await chrome.storage.local.set({ isRecording: false });
throw error;
}
}
function stopRecording() {
if (mediaRecorder && mediaRecorder.state !== 'inactive') {
mediaRecorder.stop();
}
// 停止所有轨道,这样浏览器上的 "正在共享屏幕" 提示才会消失
if (stream) {
stream.getTracks().forEach(track => track.stop());
}
// 清理
stream = null;
mediaRecorder = null;
}关键 API 解释:navigator.mediaDevices.getDisplayMedia(): 这是现代浏览器提供的标准 API,用于请求用户授权捕获屏幕、窗口或标签页。它会返回一个 MediaStream 对象。
MediaRecorder: 这个 API 接收一个 MediaStream,并将其录制成一个媒体文件。
mediaRecorder.ondataavailable: 当 MediaRecorder 收集到一块数据时,这个事件会被触发。我们将这些数据块(chunks)收集起来。
mediaRecorder.onstop: 当录制停止时,这个事件被触发。在这里,我们将所有收集到的数据块合并成一个 Blob 对象。
URL.createObjectURL(blob): 将 Blob 对象转换成一个临时的 URL,这个 URL 可以用于 <a> 标签的 href 属性,从而实现下载。
chrome.runtime.sendMessage: 用于在扩展的不同部分之间(如 popup 和 background)发送消息。
chrome.storage.local: 用于在扩展中存储少量数据,它可以在扩展的不同生命周期中保持存在。
第五步:加载和测试插件
打开 Chrome 浏览器,在地址栏输入 chrome://extensions 并回车。
在右上角,打开 “开发者模式” 的开关。
点击左上角的 “加载已解压的扩展程序” 按钮。
在弹出的文件选择器中,选择你创建的 screen-recorder-extension 整个文件夹。
如果一切顺利,你的插件图标就会出现在浏览器的工具栏上。
测试流程:
点击插件图标,弹出窗口。
点击“开始录制”。浏览器会弹出一个窗口,让你选择要录制的屏幕、应用窗口或标签页。
选择一个目标,点击“共享”。
此时,插件的 UI 会更新为“正在录制...”,并且浏览器的标签页或屏幕上会有正在共享的提示。
再次点击插件图标,然后点击“停止录制”。
录制停止,UI 更新,并出现一个“下载视频”的链接。
点击链接,即可下载你刚才录制的 webm 视频文件。
可能的改进和扩展方向
这个基础版本已经可以工作了,但还有很多可以优化的空间:
录制选项:在 popup.html 中添加选项,让用户选择是否录制麦克风声音、系统声音。
暂停和继续:使用 mediaRecorder.pause() 和 mediaRecorder.resume() 实现暂停/继续功能。
倒计时:开始录制前增加一个 3 秒倒计时。
更好的状态管理:使用 chrome.storage 更精细地管理状态,确保即使 popup 关闭,状态也能正确同步。
格式转换:录制的 webm 格式兼容性不如 mp4。你可以研究使用 ffmpeg.wasm 在浏览器端将 webm 转换为 mp4,但这会大大增加复杂性。
录制特定标签页:使用 chrome.tabCapture.capture() API 可以更精确地录制某个标签页的内容,且无需用户每次都选择。这需要额外的 "tabCapture" 权限。
网友回复
如何让ai帮我自动在小红书或抖音上自动根据需求截流与潜在客户聊天拉客?
如果用go编写一个在virtualbox中启动的简单操作系统?
go如何搭建一个零信任网络?
如何用python实现一个公网代理访问软件?
如何用go实现一个公网代理访问软件?
如何用python实现一个内网穿透打洞程序,实现内网的80端口暴露到公网上可以访问?
如何用go实现一个内网穿透打洞程序,实现内网的80端口暴露到公网上可以访问?
何为Shadowsocks 代理?
python如何实现类似php的opendir目录相互隔离的fastcgi多租户虚拟空间?
nodejs如何实现类似php的opendir目录相互隔离的fastcgi多租户虚拟空间?


