AI摘要

纯前端实现页面窗口录制,无需后端支持。使用getDisplayMedia API获取屏幕流,MediaRecorder进行录制,支持视频预览和自动下载。支持Chrome、Edge、Firefox、Safari和Opera浏览器。

JS页面窗口录制教程 📹

🎯 纯前端实现屏幕录制,无需后端支持!

🎨 效果预览

📸 在线演示

🌐 在线Demo地址

📺 操作流程展示

步骤操作说明效果预览
1️⃣ 启动录制点击录制按钮启动录制
2️⃣ 选择窗口选择录制窗口选择窗口
3️⃣ 录制中实时录制显示录制中
4️⃣ 结束下载自动下载视频完成下载

🚀 功能特色

✨ 核心功能

功能技术实现支持状态
屏幕录制getDisplayMedia API✅ 完全支持
视频预览HTML5 Video标签✅ 实时预览
自动下载Blob + download属性✅ 一键下载
格式转换WebM格式录制✅ 高兼容性
无需后端纯前端实现✅ 轻量级

🎯 技术优势

  • 🌐 纯前端:无需服务器支持
  • 📱 跨平台:支持所有现代浏览器
  • ⚡ 高性能:原生API调用,无延迟
  • 🔒 隐私安全:本地处理,不上传数据

🌐 浏览器兼容性

📊 支持情况表

浏览器版本要求支持状态备注
Chrome72+✅ 完全支持推荐使用
Edge79+✅ 完全支持Chromium内核
Firefox66+⚠️ 部分支持需要用户授权
Safari13+⚠️ 部分支持仅支持屏幕录制
Opera60+✅ 完全支持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>
最后修改:2025 年 09 月 15 日
如果觉得我的文章对你有用,请随意赞赏