WebRTC本地分享屏幕,錄製屏幕

WebRTC有分享屏幕的功能。使用的是getDisplayMedia方法。用戶同意分享屏幕後,可以拿到視頻流。
再結合MediaRecorderBlob,把視頻流數據存下來,就能得到錄製屏幕的視頻。

html

照例先來擺放一些元素在界面上

<div id="container">
<h3>WebRTC捕捉屏幕示例 getDisplayMedia</span></h1>

    <video id="gum-local" autoplay playsinline muted></video>
    <button id="startBtn" disabled>開始預覽</button>
    <button id="recordBtn" disabled>開始錄製</button>
    <button id="downloadBtn" disabled>下載</button>

    <div id="msg"></div>
</div>

<!-- 使用本地的適配器 -->
<script src="../js/adapter-latest.js" async></script>
<script src="js/main.js"></script>

因爲我的網速不是很好,把adapter文件下載到本地來用了。
如果要使用官方的適配器adapter,按下邊的地址來引入

<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
  • video 用來預覽視頻。開始分享視頻後,把視頻流交給它
  • 放置一些按鈕,處理交互
  • div#msg 用來顯示信息

控制

main.js文件裏寫上我們的控制邏輯

先把獲取元素

'use strict';

const startBtn = document.getElementById('startBtn');
const recordBtn = document.getElementById('recordBtn');
const downloadBtn = document.getElementById('downloadBtn');
const video = document.querySelector('video'); // 預覽用的

let mediaRecorder;
let isRecording = false;
let recordedBlobs = []; // 暫存視頻數據的地方

啓動屏幕分享

主要利用getDisplayMedia方法。我們這裏只使用視頻video: true

startBtn.addEventListener('click', () => {
  navigator.mediaDevices.getDisplayMedia({video: true})
      .then(gotDisplayStream, onErr);
});

// 拿到屏幕數據流
function gotDisplayStream(stream) {
  startBtn.disabled = true;
  video.srcObject = stream; // 顯示出來
  window.stream = stream;   // 緩存一下

  stream.getVideoTracks()[0].addEventListener('ended', () => {
    showMsg('用戶停止了分享屏幕');
    startBtn.disabled = false;
    recordBtn.disabled = true;
  });
  recordBtn.disabled = false;
}

function onErr(error) {
  showMsg(`getDisplayMedia on err: ${error.name}`, error);
}

function showMsg(msg, error) {
  const msgEle = document.querySelector('#msg');
  msgEle.innerHTML += `<p>${msg}</p>`;
  if (typeof error !== 'undefined') {
    console.error(error);
  }
}

拿到視頻流後,交給video顯示。
給視頻流添加事件監聽器,如果停止了分享,我們能獲得事件。

在這一步,把其它ui元素註釋掉,已經可以測試分享屏幕的效果了。
Chrome和edge會詢問用戶是否分享屏幕,並讓用戶選擇要分享的界面。mac會需要用戶修改隱私設定。
同意後,就能看到分享屏幕的效果了。

???+ note "移動端"
在手機chrome上無法分享

錄屏

上一步我們拿到了視頻流。可以仿照之前的方法把視頻流數據存下來

先來找到瀏覽器支持的視頻格式。爲了簡化操作,後面我們只選用第一種支持的格式。

// 找到支持的格式
function getSupportedMimeTypes() {
  const possibleTypes = [
    'video/webm;codecs=vp9,opus',
    'video/webm;codecs=vp8,opus',
    'video/webm;codecs=h264,opus',
    'video/mp4;codecs=h264,aac',
  ];
  return possibleTypes.filter(mimeType => {
    return MediaRecorder.isTypeSupported(mimeType);
  });
}

開始錄製

把視頻流數據推進recordedBlobs

當然這裏只是試用,實際上這麼多數據存在內存裏不妥。

function startRecording() {
  recordedBlobs = [];
  const mimeType = getSupportedMimeTypes()[0];
  const options = { mimeType };

  try {
    mediaRecorder = new MediaRecorder(window.stream, options);
  } catch (e) {
    showMsg(`創建MediaRecorder出錯: ${JSON.stringify(e)}`);
    return;
  }
  recordBtn.textContent = '停止錄製';
  isRecording = true;
  downloadBtn.disabled = true;
  mediaRecorder.onstop = (event) => {
    showMsg('錄製停止了: ' + event);
  };
  mediaRecorder.ondataavailable = handleDataAvailable;
  mediaRecorder.start();
  showMsg('錄製開始 mediaRecorder: ' + mediaRecorder);
}

function handleDataAvailable(event) {
  console.log('handleDataAvailable', event);
  if (event.data && event.data.size > 0) {
    recordedBlobs.push(event.data);
  }
}

停止錄製

mediaRecorder.stop()

function stopRecord() {
  isRecording = false;
  mediaRecorder.stop();
  downloadBtn.disabled = false;
  recordBtn.textContent = "開始錄製";
}

下載

recordedBlobs裏的數據打包好下載下來

downloadBtn.addEventListener('click', () => {
  const blob = new Blob(recordedBlobs, { type: 'video/webm' });
  const url = window.URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.style.display = 'none';
  a.href = url;
  a.download = '錄屏_' + new Date().getTime() + '.webm';
  document.body.appendChild(a);
  a.click();
  setTimeout(() => {
    document.body.removeChild(a);
    window.URL.revokeObjectURL(url);
  }, 100);
});

小結

我們使用了WebRTC的getDisplayMedia方法分享屏幕。並結合之前瞭解的下載視頻方法,實現了簡易的錄屏下載效果。

效果

效果預覽界面

原文鏈接 WebRTC本地分享屏幕,錄製屏幕

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章