思路:window.open打开标签页窗口,然后调用标签页录制,手动选择录制的新标签,然后发送message到子标签通知播放动画与声音,点击结束下载webm视频,通过ffmpeg转换成mp4格式。

完整示例代码
点击查看全文
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>录制权限控制动画播放</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
background: #f0f0f0;
}
button {
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
#status {
margin-top: 20px;
font-weight: bold;
}
</style>
</head>
<body>
<h2>录制权限控制动画播放</h2>
<button onclick="startRecording()">开始录制</button>
<div id="status">等待操作...</div>
<script>
let popupWindow = null;
let mediaRecorder = null;
// 弹出窗口的 HTML 内容(含 SVG 动画和语音播放逻辑)
const popupHTML = `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>弹出窗口</title>
<style>
body {
margin: 0;
background: #1a1a2e;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: linear-gradient(45deg, #ff6ec4, #7873f5);
animation: spin 2s linear infinite;
opacity: 0;
transform: scale(0.5);
}
.animate {
animation: spin 2s linear infinite;
opacity: 1;
transform: scale(1);
}
@keyframes spin {
0% { transform: rotate(0deg) scale(1); }
100% { transform: rotate(360deg) scale(3); }
}
</style>
</head>
<body>
<audio id="bgMusic" style="display:none;" controls="controls" src="//repo.bfw.wiki/bfwrepo/sound/5c89fd22dea6948307.mp3" ></audio>
<div class="circle" id="circle"></div>
<button id="playBtn">先点我</button>
<script>
document.getElementById('playBtn').addEventListener('click', function() {
this.style.display = "none";
});
// 监听主页面发送的消息
window.addEventListener('message', (event) => {
if (event.data === 'play') {
// 启动动画
document.getElementById('circle').classList.add('animate');
// 播放背景音乐
const audio = document.getElementById('bgMusic');
audio.play().catch(err => {
console.error('播放失败:', err);
alert('请先与页面交互(如点击按钮)以启用自动播放');
});
// 播放语音
//const utterance = new SpeechSynthesisUtterance('这是一个 SVG 动画演示');
//utterance.lang = 'zh-CN';
// utterance.rate = 1;
//utterance.pitch = 1;
//utterance.volume = 1;
//window.speechSynthesis.speak(utterance);
}
});
<\/script>
</body>
</html>
`;
async function startRecording() {
// 1️⃣ 打开手机尺寸的新标签页
const width = 1080;
const height = 1920;
const left = window.screen.width / 2 - width / 2;
const top = window.screen.height / 2 - height / 2;
popupWindow = window.open('about:blank', '_blank',
`width=${width},height=${height},left=${left},top=${top}`);
popupWindow.document.open();
popupWindow.document.write(popupHTML);
popupWindow.document.close();
document.getElementById('status').textContent = '新窗口已打开并写入内容...';
try {
// 2️⃣ 请求屏幕录制权限
document.getElementById('status').textContent = '请求屏幕录制权限...';
const displayStream = await navigator.mediaDevices.getDisplayMedia({ video: { cursor: "motion", displaySurface: "browser" }, // "browser" hints for tab
audio: true });
const tracksToRecord = [...displayStream.getTracks()]; // 包含视频+音频
combinedStreamForRecorder = new MediaStream(tracksToRecord);
// 3️⃣ 初始化 MediaRecorder
mediaRecorder = new MediaRecorder(combinedStreamForRecorder, {
mimeType: 'video/webm; codecs=vp9,opus' // 支持音频编码
});
const chunks = [];
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) chunks.push(event.data);
};
mediaRecorder.onstop = () => {
// 下载视频
const blob = new Blob(chunks, { type: 'video/webm' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'recording.webm';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
document.getElementById('status').textContent = '录制完成并已下载!';
// 关闭弹出窗口
if (popupWindow) popupWindow.close();
};
// 4️⃣ 开始录制并通知弹出窗口播放动画
mediaRecorder.onstart = () => {
document.getElementById('status').textContent = '录制已开始,通知弹出窗口播放动画...';
popupWindow.postMessage('play', '*'); // 发送播放信号
};
// 5️⃣ 启动录制
mediaRecorder.start(100); // 每 100ms 收集一次数据块
// 6️⃣ 停止录制(示例:10 秒后)
setTimeout(() => {
mediaRecorder.stop();
displayStream.getTracks().forEach(track => track.stop());
}, 10000);
} catch (err) {
console.error('录制失败:', err);
document.getElementById('status').textContent = `录制失败: ${err.message}`;
if (popupWindow) popupWindow.close();
}
}
</script>
</body>
</html>2、
网友回复


