FFmpeg 音频转换器

纯浏览器 · WebAssembly · 不上传服务器 {{ hasSab ? '跨域隔离 ✓' : '跨域隔离 ✗' }} 引擎:{{ engine }}
当前页面缺少 SharedArrayBuffer(未跨域隔离),转换一定会失败。 ffmpeg-core.wasm 是多线程(pthreads)构建,FFmpeg 6.1 的 CLI 每条输入流都要起一个解码线程, Emscripten 的线程依赖 SharedArrayBuffer,而浏览器只在跨域隔离的页面里提供它 (响应头 COOP: same-origin + COEP: require-corp)。 本目录的 coi-serviceworker.js 会用 Service Worker 自动补上这两个头, 首次访问会自己刷新一次(静态托管 dufs / nginx 默认配置 / GitHub Pages 都适用)。
仍然看到这条提示,通常是: ① 地址不是安全上下文 —— 需要 https:// 或 http://localhost / http://127.0.0.1,局域网 IP 的 http 不行(既没有 Service Worker 也没有 SharedArrayBuffer); ② 浏览器禁用/不支持 Service Worker; ③ 页面嵌在 iframe 里,而顶层页面没有隔离。 日志里出现 pthread_create() failed: Resource temporarily unavailable 就是这个原因。
Service Worker 状态:{{ coiStatus }} —— SW 已启用,但这份文档的响应没有隔离头,手动刷新(F5)一次即可(SW 只在重新加载文档后才生效)。 —— 正在启用跨域隔离,页面马上会自动刷新一次… —— Service Worker 不可用(多半不是安全上下文),只能靠服务器直接配 COOP/COEP。

1. 选择音频 / 设置参数

点击选择,或把音频文件拖到这里(可多选;再次拖入会追加,顺序 = 合并顺序) 支持 wav / mp3 / aac(m4a) / flac / ogg / opus / amr / wma / aiff / au / webm
{{ i + 1 }} {{ it.name }} {{ fmtSize(it.size) }} {{ it.path }}
共 {{ fileRows.length }} 个文件 合计时长 {{ fmtDuration(totalDuration) }}
拼接就是首尾相接(顺序可同列表里的 ↑↓ 调整);混音是几条同时播放。 各路参数(采样率/声道/编码)不一致时 FFmpeg 会在滤镜图里自动转换,不用手工处理。 多文件模式下不套用上面的裁剪条,需要剪就在「附加参数」里写 -ss / -t。
源文件信息读取中…(用 ffmpeg 探一次,大约 1~3 秒)
源文件信息{{ fileRows.length > 1 ? '(第 1 个文件)' : '' }}
格式
{{ inputInfo.format || '—' }}
时长
{{ fmtDuration(inputInfo.duration) }}
采样率
{{ inputInfo.sampleRate ? inputInfo.sampleRate + ' Hz' : '—' }}
声道
{{ channelsText(inputInfo.channels) }}
编码
{{ inputInfo.codec || '—' }}
码率
{{ inputInfo.bitrate ? inputInfo.bitrate + ' kb/s' : '—' }}
大小
{{ fmtSize(file.size) }}
起点 秒 终点 秒 保留 {{ fmtDuration(trimDuration) }} 转换时会裁剪
正在试听 {{ fmtDuration(trimStart) }} → {{ fmtDuration(trimEnd) }}{{ trimLoop ? '(循环)' : '(到终点自停)' }} 手柄之间是保留区间;试听的是原声,不含音量/倍速等滤镜。 没有波形(文件过大或浏览器解不了这种格式)——仍可拖动或直接填秒数试听;浏览器都放不了的格式(如 amr/wma)试听会失败,但转换不受影响。
注意:自定义模式不会自动套用上面的裁剪,请自己写 -ss / -t。
起点 秒 终点 秒 保留 {{ batchKeepText }}
各文件时长不同,终点超过某个文件的长度时那一条自动截到结尾。 {{ batchTrimWarn }} 配合「不重编码」就是各自快速裁剪(只搬字节)。 每个文件各自跑一条 -ss … -t …。
合并(拼接 / 混音)时不裁剪;要剪就切到「逐个转换」,或在「附加参数」里自己写 -ss / -t。
{{ copyPlan.reason }}。 采样率/声道/码率/音量/倍速也不参与 copy(已清空并置灰),附加参数里别写滤镜。
「不重编码」现在不可用:{{ copyPlan.reason }}
倍速只变速不变调:0.5~2 直接用 atempo,超范围自动串联多个 atempo; 音量与倍速会合并成一条 -af 滤镜链。
想完全手写就跑「自定义模式」,见右侧。
{{ commandPreview }}
输入是 wasm 里的虚拟路径(/input/input.bin;多文件时第 2 个起是 /input/f2.bin、/input/f3.bin…,见文件列表里的标注), 产物写在 /output/ 下; 想在本机 ffmpeg 上用,把这些路径换成真实文件路径即可(其余参数可直接照抄)。

2. 转换与下载

输入是已选文件对应的虚拟路径:第 1 个 /input/input.bin, 第 2 个起 /input/f2.bin、/input/f3.bin …(见左侧文件列表)。 产物请写到 /output/ 下。 支持多产物,见「常见命令」。产物名默认跟随输入文件:写 /output/out.mp3 会下载成 输入名.mp3; 自己起的名字(如 a_0-2s.wav)则原样保留。 一次转很多文件时,建议自己加上 -filter_threads 1(有 -filter_complex 时再加 -filter_complex_threads 1): 图形模式会自动加,它能避免浏览器同时启动一堆 wasm 线程 worker 而卡住。
{{ statusText }} 队列 {{ queueInfo }}(一个跑完才起下一个)
{{ o.name }}
{{ o.info.format }} 时长 {{ fmtDuration(o.info.duration) }} {{ o.info.sampleRate }} Hz {{ channelsText(o.info.channels) }} {{ o.info.codec }} {{ o.info.bitrate }} kb/s {{ fmtSize(o.size) }} 耗时 {{ fmtCost(o.cost) }} {{ o.at }}
不可试听 下载
FFmpeg 输出日志
{{ log }}
本页在本地跑 ffmpeg.wasm,文件不会离开你的设备。