iT邦幫忙

2024 iThome 鐵人賽

DAY 24
0
Modern Web

從 0 到 1:30 篇文章帶你玩轉 Electron 與 React系列 第 24

實作截圖功能:螢幕錄製

  • 分享至 

  • xImage
  •  

除了截圖功能,螢幕錄製是另一個實用且廣受使用者歡迎的功能,特別是在教學、遊戲錄製、錯誤報告或協作過程中,螢幕錄製可以更直觀地展示操作過程。Electron 提供了多種方式來實現螢幕錄製,包括結合 MediaStream API 和 Node.js,讓開發者可以在應用中實現靈活的螢幕錄製功能。

剛好因為工作的緣故,有使用到截圖的功能,此文章將介紹如何在 Electron 應用中實作螢幕錄製功能,並探討如何保存錄製的影片文件,管理多螢幕錄製,以及提供錄製後的編輯功能。

螢幕錄製的技術基礎

MediaStream API 是 HTML5 提供的一項功能,讓我們可以使用瀏覽器錄製螢幕或攝像頭的畫面。它同樣適用於 Electron 應用,通過與 WebRTC 相關的技術實現視訊錄製。

獲取螢幕內容

在 Electron 中,我們可以使用 navigator.mediaDevices.getDisplayMedia() 來捕捉整個螢幕或特定應用視窗的內容。這個 API 允許我們選擇螢幕作為媒體串流,並錄製該串流的內容。

async function startScreenRecording() {
  try {
    const displayStream = await navigator.mediaDevices.getDisplayMedia({
      video: {
        cursor: "always"  // 包含滑鼠游標
      },
      audio: false  // 可以根據需求決定是否錄製音訊
    });

    // 開始處理錄製的螢幕串流
    handleStream(displayStream);
  } catch (err) {
    console.error("螢幕錄製失敗:", err);
  }
}

處理錄製的螢幕串流

當我們成功取得螢幕的 MediaStream 後,可以將它交給 MediaRecorder 來進行錄製,並將錄製的片段保存在本地。

function handleStream(stream) {
  const options = { mimeType: 'video/webm; codecs=vp9' };
  const mediaRecorder = new MediaRecorder(stream, options);
  const recordedChunks = [];

  mediaRecorder.ondataavailable = (event) => {
    if (event.data.size > 0) {
      recordedChunks.push(event.data);
    }
  };

  mediaRecorder.onstop = () => {
    const blob = new Blob(recordedChunks, { type: 'video/webm' });
    downloadRecording(blob);
  };

  mediaRecorder.start();
  
  // 停止錄製可通過一個外部的事件來觸發,比如按下停止錄製按鈕
  setTimeout(() => mediaRecorder.stop(), 10000);  // 例如 10 秒後自動停止
}

function downloadRecording(blob) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = 'screen-recording.webm';
  document.body.appendChild(a);
  a.click();
  window.URL.revokeObjectURL(url);
}

錄製多螢幕內容

當系統連接了多個顯示器時,可能需要錄製特定螢幕或多個螢幕的內容。透過 getDisplayMedia(),使用者可以選擇要錄製的螢幕,並將其作為媒體串流進行處理。

選擇特定螢幕錄製

getDisplayMedia() 會自動彈出一個選擇螢幕或應用視窗的對話框,讓使用者選擇要錄製的螢幕。

async function selectScreenAndRecord() {
  try {
    const displayStream = await navigator.mediaDevices.getDisplayMedia({
      video: {
        cursor: "motion", // 只在滑鼠移動時顯示指標
        displaySurface: "monitor"  // 設定錄製類型為螢幕
      },
      audio: true // 如果需要錄製系統音頻,則啟用此選項
    });
    handleStream(displayStream);
  } catch (err) {
    console.error("螢幕錄製失敗:", err);
  }
}

錄製多個螢幕

Electron 並不直接支持多螢幕錄製,但你可以結合螢幕管理 API 和 getDisplayMedia() 來讓使用者逐個選擇不同的螢幕進行錄製,然後將多段錄製的影片合併起來。這需要在應用邏輯中設計好多螢幕選擇和管理的流程。

錄製音頻與螢幕同步

在許多錄製場景中,除了影片內容外,還需要同時錄製使用者的音頻,例如遊戲解說、會議記錄等。這時可以將音頻源加入到 getDisplayMedia() 的音頻串流中。

錄製麥克風和系統音頻

你可以使用 navigator.mediaDevices.getUserMedia() 來捕捉麥克風的音頻,並將它與螢幕串流合併。

async function startRecordingWithAudio() {
  try {
    // 獲取螢幕錄製串流
    const displayStream = await navigator.mediaDevices.getDisplayMedia({
      video: true,
      audio: true // 捕捉系統音頻
    });

    // 獲取麥克風音頻
    const audioStream = await navigator.mediaDevices.getUserMedia({
      audio: true
    });

    // 合併螢幕串流與音頻串流
    const combinedStream = new MediaStream([
      ...displayStream.getTracks(),
      ...audioStream.getTracks()
    ]);

    handleStream(combinedStream); // 將合併後的串流進行處理和錄製
  } catch (err) {
    console.error("螢幕和音頻錄製失敗:", err);
  }
}

這樣錄製的影片就包含了螢幕畫面和麥克風的語音輸入,提供完整的解說和內容記錄功能。

提供錄製控制與編輯

使用者介面控制錄製

為了讓使用者方便地控制錄製過程,你可以在應用中加入按鈕或快捷鍵來開始、暫停或停止錄製。
例如,透過一個簡單的 HTML 介面來控制:

<button id="startRecording">開始錄製</button>
<button id="stopRecording">停止錄製</button>

<script>
  const startButton = document.getElementById('startRecording');
  const stopButton = document.getElementById('stopRecording');
  
  startButton.addEventListener('click', () => startScreenRecording());
  stopButton.addEventListener('click', () => mediaRecorder.stop());
</script>

編輯錄製後的影片

錄製完成後,你可以使用第三方的影片編輯工具來進行簡單的編輯。比如使用 FFmpeg,一個開源的影片處理工具,來進行影片的裁剪、合併和格式轉換。

使用 FFmpeg 對錄製影片進行處理

將 WebM 格式轉換為 MP4
ffmpeg -i screen-recording.webm -c:v libx264 -crf 18 -preset slow screen-recording.mp4
裁剪前 30 秒的影片
ffmpeg -ss 00:00:00 -t 00:00:30 -i screen-recording.mp4 -c copy screen-recording-trimmed.mp4

你也可以通過在 Electron 中調用 FFmpeg 來自動化這些操作,為使用者提供內嵌的錄製後影片處理功能。

儲存和分享錄製的影片

在錄製完成後,你可以將影片儲存到本地文件系統,或者通過 API 上傳至雲端供分享。這裡可以結合 Node.js 的 fs 模組 來處理本地文件儲存,也可以使用 AWS S3 或其他雲端存儲服務來進行上傳。

保存錄製文件

function saveRecordingToFile(blob) {
  const fs = require('fs');
  const path = require('path');
  
  const filePath = path.join(__dirname, 'recording.mp4');
  const fileReader = new FileReader();
  
  fileReader.onload = function() {
    const buffer = Buffer.from(fileReader.result);
    fs.writeFile(filePath, buffer, () => console.log('錄製影片已保存到:', filePath));
  };

  fileReader.readAsArrayBuffer(blob);
}

上傳至雲端

使用與前面類似的 AWS S3 方式,可以將影片上傳到雲端,並提供一個可分享的連結給使用者。

總結

螢幕錄製是 Electron 應用中一項強大且實用的功能。透過結合 MediaStream APIMediaRecorder,我們可以輕鬆實現高效的螢幕錄製功能,並加入音頻錄製、多螢幕支援等進階功能。最終,我們可以提供便捷的介面來控制錄製過程,並允許使用者進行錄製後的編輯與分享,從而增強應用的互動性和功能性。

這些功能可以應用於教學軟體、遊戲錄製應用、錯誤報告工具以及多種需要記錄螢幕操作的場景中。


上一篇
實作截圖功能:進階
下一篇
建立通知與系統 Tray 應用
系列文
從 0 到 1:30 篇文章帶你玩轉 Electron 與 React25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言