Angular 19集成ffmpeg.wasm加载失败求助及视频转码替代方案咨询
解决Angular 19中ffmpeg.wasm加载失败问题及视频编码替代方案
一、修复ffmpeg.wasm加载失败问题
1. 配置Vite排除FFmpeg依赖优化
报错明确指向Vite依赖优化器与FFmpeg包不兼容,需在配置中排除相关依赖:
- 在项目根目录创建
vite.config.ts,添加以下配置:
import { defineConfig } from 'vite'; import angular from '@angular-devkit/build-angular/src/vite-plugin-angular'; export default defineConfig({ plugins: [angular()], optimizeDeps: { exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/core'] } });
- 若不想自定义Vite配置,可在
angular.json的项目build选项中关联该配置文件:
{ "projects": { "your-project-name": { "architect": { "build": { "options": { "viteConfig": "vite.config.ts" // 其他现有配置... } } } } } }
2. 修正FFmpeg Worker初始化逻辑
确保Worker文件正确加载FFmpeg核心,避免路径与加载方式错误:
在ffmpeg.worker.ts中使用官方提供的核心加载方式,无需自行托管文件:
import { FFmpeg } from '@ffmpeg/ffmpeg'; import { createFFmpegCore } from '@ffmpeg/core'; const ffmpeg = new FFmpeg(); ffmpeg.on('log', ({ message }) => console.log('FFmpeg log:', message)); async function initFFmpeg() { try { await ffmpeg.load({ core: createFFmpegCore, // 直接调用核心模块的工厂函数 }); self.postMessage({ type: 'FFMPEG_LOADED' }); } catch (err) { console.error('FFmpeg load failed:', err); self.postMessage({ type: 'FFMPEG_LOAD_ERROR', error: err.message }); } } initFFmpeg();
在cameraService中正确创建Worker实例:
export class CameraService { private ffmpegWorker: Worker | null = null; initFFmpegWorker() { this.ffmpegWorker = new Worker(new URL('./ffmpeg.worker.ts', import.meta.url), { type: 'module' }); this.ffmpegWorker.onmessage = (event) => { if (event.data.type === 'FFMPEG_LOADED') { // 执行后续视频编码逻辑 } else if (event.data.type === 'FFMPEG_LOAD_ERROR') { console.error('Worker load error:', event.data.error); } }; } }
3. 自行托管核心文件的路径验证
若坚持自行托管ffmpeg-core.js和ffmpeg-core.wasm,将文件放入src/assets目录,然后在Worker中指定路径:
await ffmpeg.load({ corePath: '/assets/ffmpeg-core.js', });
同时确保angular.json的assets配置包含这些文件:
{ "assets": [ "src/favicon.ico", "src/assets", "src/assets/ffmpeg-core.js", "src/assets/ffmpeg-core.wasm" ] }
二、视频编码替代方案
如果ffmpeg.wasm的集成问题难以解决,可考虑以下更轻量的方案:
1. 优化原生MediaRecorder配置
帧率不稳定可能是MediaRecorder参数未正确设置,尝试强制指定帧率与编码格式:
async function startRecording() { const stream = await navigator.mediaDevices.getUserMedia({ video: { width: 1280, height: 720, frameRate: { ideal: 30, max: 30 } // 强制锁定帧率 } }); const mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp9', videoBitsPerSecond: 5000000 // 5Mbps码率保证画质 }); const chunks: Blob[] = []; mediaRecorder.ondataavailable = (e) => chunks.push(e.data); mediaRecorder.onstop = () => { const videoBlob = new Blob(chunks, { type: 'video/webm' }); // 处理录制完成的视频 }; mediaRecorder.start(); }
2. 使用WebCodecs API直接编码
WebCodecs是现代浏览器提供的底层媒体编码API,性能优于ffmpeg.wasm,可精确控制帧率:
async function initWebCodecsEncoder() { const stream = await navigator.mediaDevices.getUserMedia({ video: true }); const videoTrack = stream.getVideoTracks()[0]; const trackProcessor = new MediaStreamTrackProcessor({ track: videoTrack }); const reader = trackProcessor.readable.getReader(); const chunks: Blob[] = []; const encoder = new VideoEncoder({ output: (chunk, meta) => { chunks.push(new Blob([chunk.data], { type: 'video/webm' })); }, error: (err) => console.error('Encoder error:', err) }); encoder.configure({ codec: 'vp09.00.10.08', width: videoTrack.getSettings().width || 1280, height: videoTrack.getSettings().height || 720, bitrate: 5000000, framerate: 30, hardwareAcceleration: 'prefer-hardware' }); while (true) { const { done, value } = await reader.read(); if (done) break; encoder.encode(value); value.close(); // 释放帧资源 } await encoder.flush(); const finalVideo = new Blob(chunks, { type: 'video/webm' }); // 处理最终生成的视频 }
内容的提问来源于stack exchange,提问作者Yashar Tabrizi
相关产品推荐
相关产品推荐

