163 lines
6.6 KiB
HTML
163 lines
6.6 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Chrome 原生 API 屏幕录制</title>
|
||
<style>
|
||
.control-panel { margin: 20px 0; }
|
||
button { padding: 8px 16px; margin-right: 10px; cursor: pointer; }
|
||
#preview { border: 1px solid #ccc; width: 800px; height: 450px; margin: 10px 0; }
|
||
.status { color: #666; margin: 10px 0; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="control-panel">
|
||
<button id="startBtn">开始录制</button>
|
||
<button id="pauseBtn" disabled>暂停录制</button>
|
||
<button id="resumeBtn" disabled>继续录制</button>
|
||
<button id="stopBtn" disabled>停止录制</button>
|
||
</div>
|
||
<div class="status" id="status">状态:未开始</div>
|
||
<video id="preview" autoplay muted></video>
|
||
|
||
<script>
|
||
// 核心变量
|
||
let mediaStream = null; // 屏幕捕获流
|
||
let mediaRecorder = null; // 录制器实例
|
||
let recordedChunks = []; // 录制的视频数据块
|
||
let isPaused = false; // 录制暂停状态
|
||
|
||
// DOM 元素
|
||
const startBtn = document.getElementById('startBtn');
|
||
const pauseBtn = document.getElementById('pauseBtn');
|
||
const resumeBtn = document.getElementById('resumeBtn');
|
||
const stopBtn = document.getElementById('stopBtn');
|
||
const preview = document.getElementById('preview');
|
||
const status = document.getElementById('status');
|
||
|
||
// 1. 开始录制:捕获屏幕流 + 初始化录制器
|
||
startBtn.addEventListener('click', async () => {
|
||
try {
|
||
// 步骤1:请求屏幕捕获权限(用户选择录制范围:全屏/窗口/标签页)
|
||
mediaStream = await navigator.mediaDevices.getDisplayMedia({
|
||
video: {
|
||
cursor: 'always', // 显示鼠标光标(可选:never/hidden)
|
||
frameRate: { ideal: 30, max: 60 } // 录制帧率(理想30帧,最大60帧)
|
||
},
|
||
audio: true // 同时捕获系统音频(需浏览器支持,Chrome需开启实验性功能)
|
||
});
|
||
|
||
// 步骤2:绑定流到预览窗口
|
||
preview.srcObject = mediaStream;
|
||
|
||
// 步骤3:初始化 MediaRecorder(指定录制格式为webm,Chrome 默认支持)
|
||
const options = {
|
||
mimeType: 'video/webm; codecs=vp9', // 推荐vp9编码(体积小、画质好)
|
||
// 可选:设置码率(根据需求调整,越高画质越好但体积越大)
|
||
// videoBitsPerSecond: 2500000 // 2.5Mbps
|
||
};
|
||
mediaRecorder = new MediaRecorder(mediaStream, options);
|
||
|
||
// 步骤4:监听录制数据(每块数据存入数组)
|
||
mediaRecorder.ondataavailable = (e) => {
|
||
if (e.data.size > 0) {
|
||
recordedChunks.push(e.data);
|
||
}
|
||
};
|
||
|
||
// 步骤5:监听录制结束(自动下载视频)
|
||
mediaRecorder.onstop = () => {
|
||
// 合并数据块为 Blob 视频文件
|
||
const blob = new Blob(recordedChunks, { type: 'video/webm' });
|
||
// 生成视频下载链接
|
||
const videoUrl = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = videoUrl;
|
||
a.download = `录制视频_${new Date().getTime()}.webm`;
|
||
a.click();
|
||
// 释放资源
|
||
URL.revokeObjectURL(videoUrl);
|
||
recordedChunks = [];
|
||
|
||
// 重置状态
|
||
resetRecordingState();
|
||
status.textContent = '状态:录制已停止,视频已下载';
|
||
};
|
||
|
||
// 步骤6:启动录制
|
||
mediaRecorder.start(1000); // 每1秒生成一个数据块(可选)
|
||
status.textContent = '状态:正在录制...';
|
||
|
||
// 更新按钮状态
|
||
startBtn.disabled = true;
|
||
pauseBtn.disabled = false;
|
||
stopBtn.disabled = false;
|
||
|
||
// 监听流结束(用户手动关闭捕获窗口)
|
||
mediaStream.getTracks().forEach(track => {
|
||
track.addEventListener('ended', () => {
|
||
if (mediaRecorder.state !== 'inactive') {
|
||
mediaRecorder.stop();
|
||
}
|
||
status.textContent = '状态:用户终止了屏幕捕获';
|
||
resetRecordingState();
|
||
});
|
||
});
|
||
|
||
} catch (error) {
|
||
console.error('录制启动失败:', error);
|
||
status.textContent = `状态:启动失败 - ${error.message}`;
|
||
resetRecordingState();
|
||
}
|
||
});
|
||
|
||
// 2. 暂停录制
|
||
pauseBtn.addEventListener('click', () => {
|
||
if (mediaRecorder.state === 'recording') {
|
||
mediaRecorder.pause();
|
||
isPaused = true;
|
||
status.textContent = '状态:录制已暂停';
|
||
pauseBtn.disabled = true;
|
||
resumeBtn.disabled = false;
|
||
}
|
||
});
|
||
|
||
// 3. 继续录制
|
||
resumeBtn.addEventListener('click', () => {
|
||
if (mediaRecorder.state === 'paused') {
|
||
mediaRecorder.resume();
|
||
isPaused = false;
|
||
status.textContent = '状态:正在录制...';
|
||
pauseBtn.disabled = false;
|
||
resumeBtn.disabled = true;
|
||
}
|
||
});
|
||
|
||
// 4. 停止录制
|
||
stopBtn.addEventListener('click', () => {
|
||
if (mediaRecorder.state !== 'inactive') {
|
||
// 停止录制器
|
||
mediaRecorder.stop();
|
||
// 停止所有流轨道(释放屏幕捕获)
|
||
mediaStream.getTracks().forEach(track => track.stop());
|
||
status.textContent = '状态:正在处理视频...';
|
||
}
|
||
});
|
||
|
||
// 辅助函数:重置录制状态
|
||
function resetRecordingState() {
|
||
mediaStream = null;
|
||
mediaRecorder = null;
|
||
isPaused = false;
|
||
preview.srcObject = null;
|
||
|
||
// 重置按钮
|
||
startBtn.disabled = false;
|
||
pauseBtn.disabled = true;
|
||
resumeBtn.disabled = true;
|
||
stopBtn.disabled = true;
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|