Day14 [实作] 分享画面及录影

快速测试一次分享画面的功能

在浏览器的console中输入

navigator.mediaDevices.getDisplayMedia()

https://ithelp.ithome.com.tw/upload/images/20210928/20130062spTQ73PUJ1.png

实作

常常需要录制画面的影片,又找不到好的录影软件,那我们就来自己实作一个吧

  1. index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <title>WebRTC</title>
      </head>
      <body>
        <div>
          <button id="share">分享画面</button>
          <button id="record">录影</button>
          <button id="replay" disabled>回放</button>
          <button id="download" disabled>下载</button>
        </div>
        <div>
          <video width="640" height="360" autoplay playsinline id="player"></video
          ><video width="640" height="360" autoplay id="replayer"></video>
        </div>
        <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
        <script src="./js/main.js"></script>
      </body>
    </html>
    
  2. main.js

    'use strict'
    
    // 取得标签
    const videoElement = document.querySelector('video#player')
    const recvideo = document.querySelector('video#replayer')
    const btnShare = document.querySelector('button#share')
    const btnRecord = document.querySelector('button#record')
    const btnPlay = document.querySelector('button#replay')
    const btnDownload = document.querySelector('button#download')
    
    //record
    let buffer
    let mediaRecorder
    
    // 将视讯显示在 video 标签上
    function gotStream(stream) {
      videoElement.srcObject = stream
      window.stream = stream // 录影用到
    }
    
    // 错误处理
    function handleError(error) {
      console.log(error.message, error.name)
    }
    
    // 播放自己的视讯
    function start() {
      if (window.stream) {
        window.stream.getTracks().forEach((track) => {
          track.stop()
        })
      }
      const constraints = {
        frameRate: 15,
        width: 640,
        height: 360,
      }
      navigator.mediaDevices
        .getDisplayMedia(constraints)
        .then(gotStream)
        .catch(handleError)
    }
    
    // 开始录影
    function startRecord() {
      buffer = []
    
      var options = {
        mimeType: 'video/webm;codecs=vp8',
      }
    
      if (!MediaRecorder.isTypeSupported(options.mimeType)) {
        console.error(`${options.mimeType} is not supported!`)
        return
      }
    
      try {
        mediaRecorder = new MediaRecorder(window.stream, options)
      } catch (e) {
        console.error('Failed to create MediaRecorder:', e)
        return
      }
    
      mediaRecorder.ondataavailable = (e) => {
        if (e && e.data && e.data.size > 0) {
          buffer.push(e.data)
        }
      }
      mediaRecorder.start(10)
    }
    
    // 停止录影
    function stopRecord() {
      mediaRecorder.stop()
    }
    
    // 分享画面点击
    btnShare.onclick = start
    
    // 录影按钮点击
    btnRecord.onclick = () => {
      if (btnRecord.textContent === '录影') {
        startRecord()
        btnRecord.textContent = '停止'
        btnPlay.disabled = true
        btnDownload.disabled = true
      } else {
        stopRecord()
        btnRecord.textContent = '录影'
        btnPlay.disabled = false
        btnDownload.disabled = false
      }
    }
    
    // 回放录影点击
    btnPlay.onclick = () => {
      var blob = new Blob(buffer, { type: 'video/webm' })
      recvideo.src = window.URL.createObjectURL(blob)
      recvideo.srcObject = null
      recvideo.controls = true
      recvideo.play()
    }
    
    // 下载萤幕录影
    btnDownload.onclick = () => {
      var blob = new Blob(buffer, { type: 'video/webm' })
      var url = window.URL.createObjectURL(blob)
      var a = document.createElement('a')
    
      a.href = url
      a.style.display = 'none'
      a.download = 'video.webm'
      a.click()
    }
    

<<:  Day13 - 重构产品页面 API,使用 API routes - feat. MongoDB

>>:  网页超连结-30天学会HTML+CSS,制作精美网站

[VR 前後端交响曲Day27] Rails专案开发 - 编辑ticket (使用vuex状态管理)

前情提要: 前天我们完成了新增ticket,昨天也顺便介绍了v-if语法; 今天就延续着前两天的te...

Day24 Modules & Namespaces

今天要来介绍 Module,写 Module 的好处在於,可以把程序码分成不同档案来管理,会比较好维...

如何报考CISSP?

CISSP考上心得 CISSP简介 CISSP是一个由美国(ISC)² 所颁发的资安证照,全名是C...

【Day-27】我们是怎麽开始的?:一间传统软件公司从 0 开始建置的 DevOps 文化(工具篇)- 头脑风暴

前言 昨天我们介绍了高品质工作四部法,今天让我们来介绍头脑风暴。 头脑风暴,是一种为激发创造力、强化...

[ C# 开发随笔 ] 在 Async/Await 情况使用 ReaderWriterLockSlim 出现无法解锁的状况

在 async/await 满天飞的.net core or .net 6 的专案,前阵子有人问到一...