调用摄像头录制webm (0)停止录制并且转换

Vite + Vue 使用 FFmpeg

  •               nginx 增加 response header (此header会影响非当前域名下的资源加载)
                  add_header 'Cross-Origin-Opener-Policy' 'same-origin';
                  add_header 'Cross-Origin-Embedder-Policy' 'require-corp';
    
                  如果不想更改nginx可以进入(仅PC Chrome可用)
                  https://developer.chrome.com/origintrials/#/trials/active
                  在里面找到 SharedArrayBuffers in non-isolated pages on Desktop platforms 点击注册
                  然后在页面添加
                  <meta http-equiv="origin-trial" content="注册后的token"></meta>
                  温馨提示:记得每年都定期去google续期Token哟,否者到期还是会继续报错的!
    
                  Can I use shared array buffer
                
  •               nginx gzip 增加类型不然wasm文件太大传输慢
                  gzip_types application/wasm
                
  •               页面需要是https协议 在页面控制台输入
                  crossOriginIsolated
                  返回为true即SharedArraryBuffer已启用
                
  •               npm i @ffmpeg/ffmpeg @ffmpeg/util
                
  •               下载FFmpeg依赖文件到域名根目录
                  https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.9/dist/esm/ffmpeg-core.js
                  https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.9/dist/esm/ffmpeg-core.wasm
                  https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.9/dist/esm/ffmpeg-core.worker.js
                

调用摄像头并且录制

        

          const loading = ref(false);
          const chunks = [];
          const mediaRecorder = ref(null);
          const startMediaRecorder = async() => {
            if(loading.value) return;
            loading.value = true
            try {
              const stream = await navigator.mediaDevices.getUserMedia({
                audio: true,
                video: true
              })
              document.getElementById('elA').srcObject = stream
              mediaRecorder.value = new MediaRecorder(stream); // 也可以是webrtc接收到的stream流
              mediaRecorder.value.ondataavailable = e => chunks.push(e.data);
              mediaRecorder.value.onstop = async() => {
                const blob = new Blob(chunks, { type: 'video/webm' });
                transcode(blob)
              };

              mediaRecorder.value.start();
            } catch (error) {
              console.error("录制失败", error);
            }
          }
          mediaRecorder.value.stop(); // 停止录制
        

调用FFmpeg

        

          import { FFmpeg } from '@ffmpeg/ffmpeg'
          import { fetchFile, toBlobURL } from '@ffmpeg/util'

          const transcode = async (blobOrUrl) => {
            const ffmpeg = new FFmpeg()
            ffmpeg.on('log', ({ message: msg }) => {
              console.log('log', msg)
            })
            try {
              await ffmpeg.load({
                coreURL: await toBlobURL('/resources/ffmpeg/ffmpeg-core.js', 'text/javascript'),
                wasmURL: await toBlobURL('/resources/ffmpeg/ffmpeg-core.wasm','application/wasm'),
                workerURL: await toBlobURL('/resources/ffmpeg/ffmpeg-core.worker.js', 'text/javascript')
              })
              let u8a = [] // 类型为Uint8Array
              if (Object.prototype.toString.call(blobOrUrl) === '[object Blob]') {
                const buffer = await blob.arrayBuffer();
                u8a = new Uint8Array(buffer);
              } else {
                u8a = await fetchFile(blobOrUrl) // 也可以直接用webm链接地址
              }
              await ffmpeg.writeFile('recorded.webm', u8a)
              await ffmpeg.exec(['-i', 'recorded.webm', 'recorded.mp4'])
              const data = await ffmpeg.readFile('recorded.mp4')
              let url = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }))
              const a = document.createElement('a');
              a.href = url;
              a.download = 'recorded.mp4';
              a.click();
              URL.revokeObjectURL(url);
            } catch (error) {
              console.log('转换失败', error)
            }
          }
        
京ICP备2022027730号
返回顶部