搜索
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) } }