AI摘要
纯前端实现页面窗口录制,无需后端支持。使用getDisplayMedia API获取屏幕流,MediaRecorder进行录制,支持视频预览和自动下载。支持Chrome、Edge、Firefox、Safari和Opera浏览器。
JS页面窗口录制教程 📹
🎯 纯前端实现屏幕录制,无需后端支持!
🎨 效果预览
📸 在线演示
🌐 在线Demo地址
📺 操作流程展示
步骤 | 操作说明 | 效果预览 |
---|---|---|
1️⃣ 启动录制 | 点击录制按钮 | ![]() |
2️⃣ 选择窗口 | 选择录制窗口 | ![]() |
3️⃣ 录制中 | 实时录制显示 | ![]() |
4️⃣ 结束下载 | 自动下载视频 | ![]() |
🚀 功能特色
✨ 核心功能
功能 | 技术实现 | 支持状态 |
---|---|---|
屏幕录制 | getDisplayMedia API | ✅ 完全支持 |
视频预览 | HTML5 Video标签 | ✅ 实时预览 |
自动下载 | Blob + download属性 | ✅ 一键下载 |
格式转换 | WebM格式录制 | ✅ 高兼容性 |
无需后端 | 纯前端实现 | ✅ 轻量级 |
🎯 技术优势
- 🌐 纯前端:无需服务器支持
- 📱 跨平台:支持所有现代浏览器
- ⚡ 高性能:原生API调用,无延迟
- 🔒 隐私安全:本地处理,不上传数据
🌐 浏览器兼容性
📊 支持情况表
浏览器 | 版本要求 | 支持状态 | 备注 |
---|---|---|---|
Chrome | 72+ | ✅ 完全支持 | 推荐使用 |
Edge | 79+ | ✅ 完全支持 | Chromium内核 |
Firefox | 66+ | ⚠️ 部分支持 | 需要用户授权 |
Safari | 13+ | ⚠️ 部分支持 | 仅支持屏幕录制 |
Opera | 60+ | ✅ 完全支持 | Chromium内核 |
💡 使用建议:推荐使用Chrome浏览器获得最佳体验
🔍 核心代码解析
🎯 API概览
// 核心API介绍
navigator.mediaDevices.getDisplayMedia() // 获取屏幕流
MediaRecorder // 媒体录制器
URL.createObjectURL() // 创建Blob URL
💡 代码流程图
用户点击录制 → 获取屏幕权限 → 开始录制 → 收集数据块 → 停止录制 → 生成视频 → 自动下载
📋 完整代码示例
🎨 美化版完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🎬 屏幕录制工具</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
padding: 40px;
max-width: 600px;
width: 100%;
text-align: center;
}
.title {
font-size: 2.5em;
color: #333;
margin-bottom: 10px;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.subtitle {
color: #666;
margin-bottom: 30px;
font-size: 1.2em;
}
.video-container {
margin: 30px 0;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.video {
width: 100%;
height: 400px;
background: #000;
border-radius: 15px;
}
.btn {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border: none;
padding: 15px 40px;
font-size: 1.2em;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.6);
}
.btn:active {
transform: translateY(0);
}
.btn:disabled {
background: #ccc;
cursor: not-allowed;
box-shadow: none;
}
.status {
margin-top: 20px;
padding: 15px;
border-radius: 10px;
font-weight: bold;
}
.status.recording {
background: #ffebee;
color: #c62828;
border: 1px solid #ffcdd2;
}
.status.ready {
background: #e8f5e8;
color: #2e7d32;
border: 1px solid #c8e6c9;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
margin: 30px 0;
}
.feature {
padding: 20px;
background: #f8f9fa;
border-radius: 10px;
border: 1px solid #e9ecef;
}
.feature-icon {
font-size: 2em;
margin-bottom: 10px;
}
@media (max-width: 600px) {
.container {
padding: 30px 20px;
}
.title {
font-size: 2em;
}
.video {
height: 250px;
}
}
</style>
</head>
<body>
<div class="container">
<h1 class="title">🎬 屏幕录制工具</h1>
<p class="subtitle">一键录制屏幕,无需安装任何软件</p>
<div class="features">
<div class="feature">
<div class="feature-icon">🌐</div>
<div>纯前端</div>
</div>
<div class="feature">
<div class="feature-icon">📱</div>
<div>跨平台</div>
</div>
<div class="feature">
<div class="feature-icon">⚡</div>
<div>高性能</div>
</div>
<div class="feature">
<div class="feature-icon">🔒</div>
<div>隐私安全</div>
</div>
</div>
<div class="video-container">
<video class="video" controls></video>
</div>
<button class="btn" onclick="startRecording()">🎥 开始录制</button>
<div class="status ready" id="status">准备就绪,点击开始录制</div>
</div>
<script>
let mediaRecorder;
let recordedChunks = [];
async function startRecording() {
try {
const status = document.getElementById('status');
const btn = document.querySelector('.btn');
// 获取屏幕流
const stream = await navigator.mediaDevices.getDisplayMedia({
video: { mediaSource: 'screen' },
audio: true
});
// 设置录制格式
const mimeType = MediaRecorder.isTypeSupported('video/webm; codecs=vp9')
? 'video/webm; codecs=vp9'
: 'video/webm';
mediaRecorder = new MediaRecorder(stream, { mimeType });
// 收集数据块
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) {
recordedChunks.push(event.data);
}
};
// 录制完成处理
mediaRecorder.onstop = () => {
const blob = new Blob(recordedChunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
// 显示视频
const video = document.querySelector('.video');
video.src = url;
// 自动下载
const a = document.createElement('a');
a.href = url;
a.download = `screen-record-${new Date().getTime()}.webm`;
a.click();
// 重置状态
recordedChunks = [];
status.textContent = '录制完成,视频已下载';
status.className = 'status ready';
btn.textContent = '🎥 重新录制';
btn.disabled = false;
};
// 开始录制
mediaRecorder.start();
status.textContent = '⏺️ 正在录制...';
status.className = 'status recording';
btn.textContent = '⏹️ 停止录制';
// 监听流结束
stream.getVideoTracks()[0].onended = () => {
mediaRecorder.stop();
};
// 添加停止录制按钮功能
btn.onclick = () => {
mediaRecorder.stop();
stream.getTracks().forEach(track => track.stop());
};
} catch (error) {
console.error('录制失败:', error);
alert('录制失败: ' + error.message);
document.getElementById('status').textContent = '录制失败,请重试';
document.getElementById('status').className = 'status ready';
}
}
</script>
</body>
</html>