思路: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、
网友回复
为啥所有的照片分辨率提升工具都会修改照片上的图案细节?
js如何在浏览器中将webm视频的声音分离为单独音频?
微信小程序如何播放第三方域名url的mp4视频?
ai多模态大模型能实时识别视频中的手语为文字吗?
如何远程调试别人的chrome浏览器获取调试信息?
为啥js打开新网页window.open设置窗口宽高无效?
浏览器中js的navigator.mediaDevices.getDisplayMedia屏幕录像无法录制SpeechSynthesisUtterance产生的说话声音?
js中mediaRecorder如何录制window.speechSynthesis声音音频并下载?
python如何直接获取抖音短视频的音频文件url?
js在浏览器中如何使用MediaStream与MediaRecorder实现声音音频多轨道混流?