前端屏幕录制示例

 

示例一:只有画面,没有声音

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>rrweb demo web site</title> <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/rrweb.min.js"></script> <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb@latest/dist/record/rrweb-record.min.js"></script> <link rel="stylesheet" crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/style.css" /> <script crossorigin="anonymous" src="https://cdn.jsdelivr.net/npm/rrweb-player@latest/dist/index.js"></script> </head> <body> <h1 class="some-title">this is some title for test</h1> <input type="button" value="开始录制" onclick="record()" /> <br /> <input type="button" value="结束录制" onclick="replay()" /> <div id="replaycontent"> </div> <script> window.events = []; function record() { rrweb.record({ emit(event) { // 将 event 存入 events 数组中 events.push(event); console.log(event); }, }); } function replay() { new rrwebPlayer({ target: document.getElementById("replaycontent"), // 可以自定义 DOM 元素 data: { events, }, }); } // save 函数用于将 events 发送至后端存入,并重置 events 数组 function save() { const body = JSON.stringify(window.events); console.log(body) events = []; // fetch("http://localhost:8080/api", { fetch("D://", { method: "POST", headers: { "Content-Type": "application/json", }, body, }); } // 每 10 秒调用一次 save 方法,避免请求过多 // setInterval(save, 10 * 1000); </script> </body> </html>

示例二:基于分享页面来实现

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <title>在线屏幕录制</title> <style> body{ font-family: Arial; margin: 4vh auto; width: 90vw; max-width: 600px; text-align: center; } #controls{ text-align: center; } .btn{ margin: 10px 5px; padding: 15px; background-color: #2bcbba; border: none; color: white; font-weight: bold; border-radius: 6px; outline: none; font-size: 1.2em; width: 120px; height: 50px; } .btn:hover{ background-color: #26de81; cursor: hand; } .btn:disabled{ background-color: #2bcbba80; } #stop{ background-color: #fc5c65; } #video{ margin-top: 10px; margin-bottom: 20px; border: 12px solid #a5adb0 ; border-radius: 15px; outline: none; width: 100%; height: 400px; background-color: black; } h1{ color: #2bcbba; letter-spacing:-2.5px; line-height: 30px; } .created{ color: lightgrey; letter-spacing: -0.7px; font-size: 1em; margin-top: 40px; } .created > a{ color: #4b7bec; text-decoration: none; } </style> </head> <body> <h1><u style='color:#fc5c65'>在线屏幕录制</u><br>支持 :新版本 Chrome,Edge,Firefox 桌面浏览器 <br></h1> <video autoplay='true' id='video' controls='true' controlsList='nodownload'></video> <button class='btn' id='record' onclick='record()'>录制</button> <button style='display: none' class='btn' id='stop' onclick='stop()'>停止</button> <button disabled='true' class='btn' id='download' onclick='download()'>下载</button> <div class='created'> </div> </body> <script> const video = document.getElementById('video') const downloadBtn = document.getElementById('download') const recordBtn = document.getElementById('record') const stopBtn = document.getElementById('stop') let recorder async function record() { // 开始录屏 let captureStream try{ captureStream = await navigator.mediaDevices.getDisplayMedia({ video: true, // audio: true, not support cursor: 'always' }) }catch(e){ // 取消录屏或者报错 alert("Could not get stream") return } downloadBtn.disabled = true recordBtn.style = 'display: none' stopBtn.style = 'display: inline' // 删除之前的 Blob window.URL.revokeObjectURL(video.src) video.autoplay = true // 实时的播放录屏 video.srcObject = captureStream // new 一个媒体记录 recorder = new MediaRecorder(captureStream) recorder.start() captureStream.getVideoTracks()[0].onended = () => { // 录屏结束完成 recorder.stop() } recorder.addEventListener("dataavailable", event => { // 录屏结束,并且数据可用 console.log("dataavailable------------") let videoUrl = URL.createObjectURL(event.data, {type: 'video/ogg'}) video.srcObject = null video.src = videoUrl video.autoplay = false downloadBtn.disabled = false recordBtn.style = 'display: inline' stopBtn.style = 'display: none' }) } function download(){ // 下载 const url = video.src const name = new Date().toISOString().slice(0, 19).replace('T',' ').replace(" ","_").replace(/:/g,"-") const a = document.createElement('a') a.style = 'display: none' a.download = `${name}.ogg` a.href = url document.body.appendChild(a) a.click() } function stop(){ let tracks = video.srcObject.getTracks() tracks.forEach(track => track.stop()) recorder.stop() } </script> </html>

示例三:单独录制声音

<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>小猿圈</title> </head> <body> <div> <audio autoplay></audio> <input onclick="startRecording()" type="button" value="录音" /> <input onclick="stopRecording()" type="button" value="停止" /> <input onclick="playRecording()" type="button" value="播放" /> <input onclick="uploadAudio()" type="button" value="提交" /> <br /> <div id="recordingslist"></div> </div> <script type="text/javascript" src="./HZRecorder.js"></script> <script> var recorder; var audio = document.querySelector('audio'); function startRecording() { HZRecorder.get(function(rec) { recorder = rec; recorder.start(); }, { sampleBits: 16, sampleRate: 16000 }); } function stopRecording() { recorder.stop(); var blob = recorder.getBlob(); var url = URL.createObjectURL(blob); var div = document.createElement('div'); var au = document.createElement('audio'); var hf = document.createElement('a'); au.controls = true; au.src = url; hf.href = url; hf.download = new Date().toISOString() + '.wav'; hf.innerHTML = hf.download; div.appendChild(au); div.appendChild(hf); recordingslist.appendChild(div); } function playRecording() { recorder.play(audio); } function uploadAudio() { recorder.upload("Handler1.ashx", function(state, e) { switch(state) { case 'uploading': //var percentComplete = Math.round(e.loaded * 100 / e.total) + '%'; break; case 'ok': //alert(e.target.responseText); alert("上传成功"); break; case 'error': alert("上传失败"); break; case 'cancel': alert("上传被取消"); break; } }); } </script> </body> </html>

示例四:可以录制视频和声音可以截图和下载,但是只能录制一条流

<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title></title> <style> video { border: 1px solid #ccc; display: block; margin: 0 0 20px 0; float:left; } canvas { margin-top: 20px; border: 1px solid #ccc; display: block; } </style> </head> <body> <video width="640" height="480" id="myVideo"></video> <canvas width="640" height="480" id="myCanvas"></canvas> <button id="startVideo">开始录制</button> <button id="endVideo">结束录制</button> <button id="myButton">截图</button> <button id="myButton3"> <a download="video.png">另存为</a> </button> </body> <script> window.addEventListener('DOMContentLoaded',function(){ var cobj=document.getElementById('myCanvas').getContext('2d'); var vobj=document.getElementById('myVideo'); getUserMedia({video:true,audio:true},function(stream){ console.log(stream) // vobj.src=stream; try { vobj.srcObject = stream; } catch (e) { try { vobj.src = URL.createObjectURL(stream); } catch (e) { console.error("Error attaching stream to element"); } } vobj.play(); let options = { audioBitsPerSecond : 128000, // 音频码率 videoBitsPerSecond : 100000, // 视频码率 mimeType:'video/webm;codecs=h264' } let localMediaRecorder = new MediaRecorder(stream, options) document.getElementById("startVideo").addEventListener("click",function(){ // 开始采集 localMediaRecorder.start() console.log('开始采集') }) document.getElementById("endVideo").addEventListener("click",function(){ // 停止采集 localMediaRecorder.stop() console.log('停止采集') }) // 事件 localMediaRecorder.ondataavailable = function (e) { console.log(e) // 下载视频 var blob = new Blob([e.data], { 'type' : 'video/mp4' }) let a = document.createElement('a') a.href = URL.createObjectURL(blob) alert(URL.createObjectURL(blob)) a.download = `test.mp4` a.click() } },function(){}); document.getElementById('myButton').addEventListener('click',function(){ cobj.drawImage(vobj,0,0,640,480); document.getElementById('myButton3').children[0].href=cobj.canvas.toDataURL("image/png"); },false); },false); function getUserMedia(obj,success,error){ // if(navigator.getUserMedia){ // alert("1"+navigator.getUserMedia) getUserMedia=function(obj,success,error){ navigator.getUserMedia(obj,function(stream){ success(stream); },error); } // }else if(navigator.webkitGetUserMedia){ // alert("2"+navigator.webkitGetUserMedia) // getUserMedia=function(obj,success,error){ // navigator.webkitGetUserMedia(obj,function(stream){ // var _URL=window.URL || window.webkitURL; // success(_URL.createObjectURL(stream)); // },error); // } // }else if(navigator.mozGetUserMedia){ // alert("3"+navigator.mozGetUserMedia) // getUserMedia=function(obj,success,error){ // navigator.mozGetUserMedia(obj,function(stream){ // success(window.URL.createObjectURL(stream)); // },error); // } // }else{ // return false; // } return getUserMedia(obj,success,error); } </script> </html>

 


__EOF__

本文作者皮军旗
本文链接https://www.cnblogs.com/pijunqi/p/14480346.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   皮军旗  阅读(440)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
点击右上角即可分享
微信分享提示