這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 要在 JavaScript 中實現屏幕錄製,可以使用 navigator.mediaDevices.getDisplayMedia() 方法來獲取屏幕的媒體流。然後,可使用 MediaRecorder 對象將媒體流錄製為視頻文件。 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
前言
要在 JavaScript 中實現屏幕錄製,可以使用 navigator.mediaDevices.getDisplayMedia()
方法來獲取屏幕的媒體流。然後,可使用 MediaRecorder
對象將媒體流錄製為視頻文件。
但該方法會在瀏覽器彈出一個授權視窗,讓用戶選擇要分享的內容,這不可實現“無感知”。
如果真正做到無感知,那我們就不能藉助瀏覽器或者系統系統的能力了。我們能做的就只能是通過js去操作了。
要在頁面內直接錄製視頻似乎並不容易,沒有現成的開源庫可以使用,也沒有很好的想法。
那我們換一個思路,視頻是由幀組成的,我們是否可以不斷的截圖,然後組合成一段視頻?好像是可以的
頁面
先寫一個簡單的頁面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas視頻錄製</title> <link rel="stylesheet" href="styles.css"> </head> <body> <main> <div class="buttons"> <button class="start-btn">開始錄製</button> <button class="pause-btn">暫停錄製</button> <button class="resume-btn">繼續錄製</button> <button class="stop-btn">結束錄製</button> </div> <div id="box"> <section class="content"> <h2>TODO LIST</h2> <div class="background-div"> <button class="background-btn">切換背景顏色</button> </div> <div id="todo-form"> <input type="text" class="input-field" placeholder="輸入待辦事項"> <button type="submit" class="submit-btn">提交</button> </div> <div class="list"></div> </section> </div> <img src="" alt="" class="hidden"> </main> <script src="<https://cdn.bootcss.com/html2canvas/0.5.0-beta4/html2canvas.min.js>" defer></script> <script src="canvas.js" defer></script> </body> </html>
截圖
實現網頁的截圖操作,最常用的庫是 html2canvas
用,它可以將網頁中的 HTML 元素轉換為 Canvas 元素,並將其導出為圖像文件。在瀏覽器中捕獲整個頁面或特定區域的截圖,包括 CSS 樣式和渲染效果。
const canvasFunction = () => { html2canvas(box).then(canvas => { const imgStr = canvas.toDataURL("image/png"); img.src = imgStr; img.onload = function () { ctx.drawImage(img, 0, 0, w, h); } }); }
合成視頻
這裡我們要使用到一個 API MediaRecorder
,用於在瀏覽器中進行音頻和視頻的錄製。它提供了一種簡單的方式來捕獲來自麥克風、攝像頭或屏幕的媒體數據,並將其保存為文件或進行實時流傳輸。
它有以下幾個常用的方法:
isTypeSupported()
返回一個 Boolean 值,來表示設置的 MIME type 是否被當前用戶的設備支持。start()
開始錄製媒體,這個方法調用時可以通過給timeslice
參數設置一個毫秒值,如果設置這個毫秒值,那麼錄製的媒體會按照你設置的值進行分割成一個個單獨的區塊,而不是以預設的方式錄製一個非常大的整塊內容。pause()
暫停媒體錄製。resume()
繼續錄製之前被暫停的錄製動作。stop()
停止錄製。同時觸發dataavailable
事件,返回一個存儲Blob
內容的錄製數據。之後不再記錄。
首先創建一個 canvas
元素,用來保存 html2canvas
的截圖,然後通過 captureStream
方法實時截取媒體流。
const w = boxBoundingClientRect.width; const h = boxBoundingClientRect.height; const canvas = document.createElement('canvas'); canvas.setAttribute('id', 'canvas'); canvas.setAttribute('width', w); canvas.setAttribute('height', h); canvas.style.display = 'none'; box.appendChild(canvas); const img = document.querySelector('img'); const ctx = canvas.getContext("2d"); const allChunks = []; const stream = canvas.captureStream(60); // 60 FPS recording 1秒60幀通過 canvas 的流來創建一個
MediaRecorder
實例,併在 ondataavailable
事件中保存視頻信息:const recorder = new MediaRecorder(stream, { mimeType: 'video/webm;codecs=vp9' }); recorder.ondataavailable = (e) => { allChunks.push(e.data); };
最後,在停止錄製時將幀信息創建 blob 並插入到頁面上:
recorder.stop(); const fullBlob = new Blob(allChunks); const videoUrl = window.URL.createObjectURL(fullBlob); const video = document.createElement('video'); video.controls = true; video.src = videoUrl; video.muted = true; video.autoplay = true; document.body.appendChild(video);
或者可以將視頻下載
recorder.stop(); const fullBlob = new Blob(allChunks); const videoUrl = window.URL.createObjectURL(fullBlob); let link = document.createElement('a'); link.style.display = 'none'; let fullBlob = new Blob(allChunks); let downloadUrl = window.URL.createObjectURL(fullBlob); link.href = downloadUrl; link.download = 'canvas-video.mp4'; document.body.appendChild(link); link.click(); link.remove();
這裡,為了節省資源,只在點擊按鈕、輸入等事件發生時才調用 html2canvas
截圖 DOM。
如果實時記錄屏也可以使用 requestAnimationFrame
。
最後
雖然實現了無感知錄製屏幕,但也僅限於網頁內,沒有辦法錄製網頁以外的部分。