Next.js中用ffmpegwasm前端转MP3/MP4为WAV遇模块未找到错误
解决Next.js中ffmpeg.wasm的"Module not found"错误
问题背景
在Next.js项目中使用ffmpeg.wasm实现前端MP3/MP4转WAV功能时,遇到Module not found错误,已升级至最新版Next.js,问题仍未解决。
错误信息
./node_modules/@ffmpeg/ffmpeg/dist/esm/classes.js:104:27 Module not found 102 | if (!this.#worker) { 103 | this.#worker = classWorkerURL ? > 104 | new Worker(new URL(classWorkerURL, import.meta.url), { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 105 | type: "module", 106 | }) : 107 | // We need to duplicated the code here to enable webpack
问题代码片段
"use client" import { FFmpeg } from "@ffmpeg/ffmpeg" import { fetchFile, toBlobURL } from "@ffmpeg/util" import React, { useEffect, useRef, useState } from "react" export default function TestPage() { const [loaded, setLoaded] = useState(false) const ffmpegRef = useRef(new FFmpeg()) const messageRef = useRef(null) useEffect(() => { load() }, []) const load = async () => { const baseURL = "https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd" const ffmpeg = ffmpegRef.current ffmpeg.on("log", ({ message }) => { if (messageRef.current) messageRef.current.innerHTML = message console.log(message) }) await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, "application/wasm"), }) setLoaded(true) } const convertToWav = async ({ target: { files } }) => { const ffmpeg = ffmpegRef.current const file = files[0] await ffmpeg.writeFile("input.mp4", await fetchFile(file)) await ffmpeg.exec(["-i", "input.mp4", "output.wav"]) const data = await ffmpeg.readFile("output.wav") const url = URL.createObjectURL(new Blob([data.buffer], { type: "audio/wav" })) const link = document.createElement("a") link.href = url link.setAttribute("download", "output.wav") document.body.appendChild(link) link.click() } return ( <div> {loaded ? ( <> <input type="file" onChange={convertToWav} accept="audio/mp3,video/mp4" /> <p ref={messageRef}></p> </> ) : ( <button onClick={load}>Load ffmpeg-core</button> )} </div> ) }
已尝试方案
- 升级至最新版Next.js
- 尝试多种ffmpeg实例配置
解决方案
1. 修复"Module not found"错误
错误根源是Next.js打包器无法解析ffmpeg.wasm内部的new URL(classWorkerURL, import.meta.url)语法,可通过以下两步解决:
步骤1:配置Next.js转译ffmpeg相关包
在项目根目录的next.config.js中添加transpilePackages配置,让Next.js正确处理ffmpeg的ESM代码:
/** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ['@ffmpeg/ffmpeg', '@ffmpeg/util'], } module.exports = nextConfig
步骤2:手动指定Worker路径
修改FFmpeg实例初始化逻辑,手动传入Worker的CDN地址,避免内部路径解析错误:
// 替换原有的ffmpegRef初始化 const ffmpegRef = useRef(null) const load = async () => { const baseURL = "https://unpkg.com/@ffmpeg/core@0.12.6/dist/umd" // 手动指定Worker的CDN地址,确保与ffmpeg版本匹配 const workerURL = await toBlobURL("https://unpkg.com/@ffmpeg/ffmpeg@0.12.6/dist/umd/ffmpeg-worker.js", "text/javascript") // 初始化FFmpeg实例时传入workerURL const ffmpeg = new FFmpeg({ workerURL }) ffmpegRef.current = ffmpeg ffmpeg.on("log", ({ message }) => { if (messageRef.current) messageRef.current.innerHTML = message console.log(message) }) await ffmpeg.load({ coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"), wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, "application/wasm"), }) setLoaded(true) }
2. Next.js使用ffmpeg.wasm的注意事项
- 强制使用客户端组件:必须在组件顶部添加
"use client"指令,ffmpeg.wasm依赖浏览器环境的Worker、Blob等API,无法在服务器端执行。 - 版本严格匹配:确保
@ffmpeg/ffmpeg与@ffmpeg/core的版本完全一致,版本不兼容会导致加载失败或功能异常。 - 优先使用CDN资源:通过CDN加载ffmpeg核心文件(core.js、wasm、worker.js),减少本地打包体积,同时避免本地资源路径解析问题。
- 添加加载状态:ffmpeg核心文件体积较大,加载需要时间,务必提供加载状态提示,避免用户误操作。
- 内存限制处理:浏览器对Wasm内存有默认限制,处理大文件时可通过
FFmpeg构造函数的memSize参数调整内存分配。
内容的提问来源于stack exchange,提问作者ryuma
相关产品推荐
相关产品推荐

