iT邦幫忙

2021 iThome 鐵人賽

DAY 13
0
Modern Web

後疫情時代的 WebRTC 微學習系列 第 13

Day13 [實作] 把視訊及音訊內容錄製下來

本篇我們將實作音視訊的錄製並下載,內容包含:

  1. 錄製影片

  2. 回放影片

  3. 下載影片

  4. 複製上一篇程式碼

    cp -r take-a-photo video-recording
    
  5. index.html 中 將 video playbutton 替換為以下

    <div><video autoplay playsinline id="player"></video></div>
    <div><button id="shoot">拍照</button></div>
    

    替換為

    <div>
      <video autoplay playsinline id="player"></video>
      <video autoplay id="replayer"></video>
    </div>
    <div>
      <button id="shoot">拍照</button>
      <button id="record">錄影</button>
      <button id="replay" disabled>回放</button>
      <button id="download" disabled>下載</button>
    </div>
    
    1. 加入一個 id 為 replayer 的 video
    2. 加入三個按鈕 錄影回放下載
  6. main.js 實作

    在原本的方法中增加 window.stream = stream

    // 將視訊顯示在 video 標籤上
    function gotStream(stream) {
      videoElement.srcObject = stream
    +  window.stream = stream  // 增加這段,錄影需要取得stream
      return navigator.mediaDevices.enumerateDevices()
    }
    

    在後面加上錄影的程式碼:

    //record
    let buffer
    let mediaRecorder
    
    const recvideo = document.querySelector('video#replayer');
    const btnRecord = document.querySelector('button#record');
    const btnPlay = document.querySelector('button#replay');
    const btnDownload = document.querySelector('button#download');
    
    function handleDataAvailable(e) {
      if (e && e.data && e.data.size > 0) {
        buffer.push(e.data)
      }
    }
    
    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 = handleDataAvailable
      mediaRecorder.start(10)
    }
    
    function stopRecord() {
      mediaRecorder.stop()
    }
    
    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()
    }
    

    題外話:檢查瀏覽器支援哪些 Type

    可以在瀏覽器的 console 中輸入以下

    function getSupportedMimeTypes() {
      const VIDEO_TYPES = ['webm', 'ogg', 'mp4', 'x-matroska']
      const VIDEO_CODECS = [
        'vp9', 'vp9.0', 'vp8', 'vp8.0', 'avc1', 'av1',
        'h265', 'h.265', 'h264', 'h.264', 'opus'
      ]
    
      const supportedTypes = []
      VIDEO_TYPES.forEach((videoType) => {
        const type = `video/${videoType}`
        VIDEO_CODECS.forEach((codec) => {
          const variations = [
            `${type};codecs=${codec}`,
            `${type};codecs:${codec}`,
            `${type};codecs=${codec.toUpperCase()}`,
            `${type};codecs:${codec.toUpperCase()}`,
            `${type}`,
          ]
          variations.forEach((variation) => {
            if (MediaRecorder.isTypeSupported(variation))
              supportedTypes.push(variation)
          })
        })
      })
      return supportedTypes
    }
    
    const supportedMimeTypes = getSupportedMimeTypes()
    console.log('Best supported mime types by priority : ', supportedMimeTypes[0])
    console.log(
      'All supported mime types ordered by priority : ',
      supportedMimeTypes,
    )
    

上一篇
Day12 [實作] 使用瀏覽器來拍照並加上濾鏡
下一篇
Day14 [實作] 分享畫面及錄影
系列文
後疫情時代的 WebRTC 微學習30

尚未有邦友留言

立即登入留言