我写了个不用上传的浏览器视频压缩工具,顺便记一个坑了我小半天的 bug

起因很土。我经常要把录屏发到 Discord 或者塞进邮件,Discord 免费版限 10MB,邮箱附件常见 25MB,而一段两三分钟的 1080p 录屏动不动几十兆。网上的在线压缩工具能用,但每次都得先把视频传到人家服务器,压完再下回来。慢是一回事,更别扭的是,我不太想把公司内部的录屏传到一个不知道是谁的服务器上。

于是我做了 videocompress.dev,压缩全程跑在你自己浏览器里,视频不上传,一个字节都不出你的电脑。

它是怎么跑起来的

主力是 WebCodecs,浏览器原生的编解码接口,能直接调硬件编码器,速度接近实时。碰上不支持的浏览器,退回到 ffmpeg.wasm(把 FFmpeg 编译成 WebAssembly 在本地跑)。两条路都不碰服务器,我这边的成本基本只有一个静态托管。压到指定大小还是保画质都行,Discord、邮件、WhatsApp 这些场景我做了预设。

一个让我排查了小半天的 bug

本以为这就完事了。直到我拿一个 46 分钟的录屏去测,压出来是个"没有画面、只有声音"的文件。最诡异的是:全程不报错,程序自认为成功了。

我在解码管线上加了个计数器,数到底多少帧真进了编码器,结果是 0。视频轨一帧都没解出来,音频轨却好好的。换个 60 秒的短片又完全正常。我一开始赌是时长或内存问题,后来发现都不是。

真正的原因是容器。这个文件第一帧的 DTS 是负的(B 帧重排很常见,首帧的解码时间戳会落在 0 之前一点点)。我用的解码库默认从时间戳 0 开始读,在 0 这个点找不到能解码的起始帧,就一帧不吐,还不报错,直接甩给你一个纯音频文件。更阴的是 ffprobe 默认会把这个负值归一化,光看它根本发现不了,得去读原始 packet 的 DTS 才看得见。

修法说穿了不复杂:先用 ffmpeg 无损重封装一下(-c copy 加上 -avoid_negative_ts make_zero,把时间戳掰正,不重新编码,几十秒的事),再把干净的文件喂回 WebCodecs。同一个 46 分钟的文件,纯 ffmpeg 软件转码要跑 87 分钟,重封装加 WebCodecs 之后是 3 到 4 分钟。

写这段一半是记录,一半是提醒自己:浏览器里搞音视频,坑基本都在边缘情况上,而且经常是静默失败,连个 error 都不给你留。

最后

现在 videocompress.dev 免费、免注册、无水印,视频不上传。你要是也常被"文件太大发不出去"卡住,可以拿去用。有压不动或者出问题的文件,欢迎丢给我,我最想收集的就是这种能触发边缘 case 的样本。

相关推荐
Carol06301 天前
2026.10.18_科目一
private
Carol06305 天前
2026.10.15_科目一
private
不当菜鸡的程序媛12 天前
Wan 1.3B 结构维度
video
不当菜鸡的程序媛14 天前
video中的memory kv cache
video
纪伊路上盛名在1 个月前
Github workflow中如何设置private环境变量
github·workflow·actions·private·api key
Cerman1 个月前
UEFI GOP driver基础协议解读
video·uefi·gop·edid·gfx
mengyuxuan2 个月前
在浏览器里做视频压缩,我踩的三个坑
video·compressor·compress
山顶夕景2 个月前
【全模态】音视频理解模型Audio-Visual Flamingo
音视频·video·vlm·多模态理解
YMWM_3 个月前
video.preset的值为null和ultrafast的区别
linux·video