在CRA React应用中使用ffmpeg.wasm时出现Babel Loader错误
CRA集成ffmpeg-wasm遇Module Parse失败错误
依赖版本
"@ffmpeg/ffmpeg": "^0.12.10", "@ffmpeg/util": "^0.12.1",
组件实现代码
import React, {useRef, useState} from 'react'; import { FFmpeg } from "@ffmpeg/ffmpeg"; import { toBlobURL, fetchFile } from "@ffmpeg/util"; function Trimmer() { const [loaded, setLoaded] = useState(false); const ffmpegRef = useRef(new FFmpeg()); const videoRef = useRef<HTMLVideoElement | null>(null) const messageRef = useRef<HTMLParagraphElement | null>(null) const load = async () => { const baseURL = "https://unpkg.com/@ffmpeg/core-mt@0.12.6/dist/esm"; const ffmpeg = ffmpegRef.current; ffmpeg.on("log", ({ message }) => { if (messageRef.current) messageRef.current.innerHTML = message; }); // toBlobURL is used to bypass CORS issue, urls with the same // domain can be used directly. await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"), wasmURL: await toBlobURL( `${baseURL}/ffmpeg-core.wasm`, "application/wasm" ), workerURL: await toBlobURL( `${baseURL}/ffmpeg-core.worker.js`, "text/javascript" ), }); setLoaded(true); }; const transcode = async () => { const videoURL = "https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi"; const ffmpeg = ffmpegRef.current; await ffmpeg.writeFile("input.avi", await fetchFile(videoURL)); await ffmpeg.exec(["-i", "input.avi", "output.mp4"]); const fileData = await ffmpeg.readFile('output.mp4'); const data = new Uint8Array(fileData); if (videoRef.current) { videoRef.current.src = URL.createObjectURL( new Blob([data.buffer], { type: 'video/mp4' }) ) } }; return loaded ? ( <> <video ref={videoRef} controls></video> <br /> <button onClick={transcode}>Transcode avi to mp4</button> <p ref={messageRef}></p> </> ) : ( <button onClick={load}>Load ffmpeg-core</button> ); } export default Trimmer;
启动报错信息
index.js:1 ./node_modules/@ffmpeg/ffmpeg/dist/umd/ffmpeg.js 55:4 Module parse failed: Unexpected character '#' (55:4) File was processed with these loaders: * ./node_modules/babel-loader/lib/index.js You may need an additional loader to handle the result of these loaders. | new Error("failed to import ffmpeg-core.js"); | class i { > #e = null; | #t = {}; | #s = {};
当前环境版本
- React: 16.14.0
- NPM: 6.14.5
- Babel Loader: 8.1.0
错误原因
报错中的#e = null是ES6类私有字段语法,你的CRA默认Babel配置未启用该语法的解析支持,导致Babel无法处理这部分代码。
解决方案
方案1:降级ffmpeg-wasm版本
0.12.x版本的ffmpeg-wasm使用了类私有字段,旧版CRA不支持,降级到兼容的0.11.x版本即可:
- 卸载现有依赖
npm uninstall @ffmpeg/ffmpeg @ffmpeg/util
- 安装指定版本
npm install @ffmpeg/ffmpeg@0.11.6 @ffmpeg/util@0.11.0
- 调整组件代码适配旧版API:
- 导入路径修改:
fetchFile从@ffmpeg/ffmpeg导入,而非@ffmpeg/util - 加载核心的方式改为
loadCore:await ffmpeg.loadCore(await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript")); writeFile、exec等其他API用法基本一致
- 导入路径修改:
方案2:修改Babel配置支持私有字段(无需降级)
通过react-app-rewired修改CRA配置,无需eject:
- 安装依赖
npm install react-app-rewired customize-cra --save-dev
- 项目根目录创建
config-overrides.js文件:
const { override, addBabelPlugins } = require('customize-cra'); module.exports = override( addBabelPlugins( '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-private-methods', '@babel/plugin-proposal-private-property-in-object' ) );
- 修改
package.json中的启动脚本:
"scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test", "eject": "react-scripts eject" }
- 重启项目即可
内容的提问来源于stack exchange,提问作者Sooraj Chandu
相关产品推荐
相关产品推荐

