跳到正文
DEV Community· lucas2324343·· 3 小時前AI 評分56

OxiPNG、SVGO、rembg 和 FFmpeg 在瀏覽器分頁運作:哪些做法實際可行

Running OxiPNG, SVGO, rembg and FFmpeg in a browser tab: what actually worked

AI 導讀

作者把 OxiPNG、SVGO、rembg 相關模型及 FFmpeg 整合到可在瀏覽器分頁運作的工具頁,並交代各自的執行方式和限制。OxiPNG 頁面只提供 1–4 級,壓縮後若沒有變小便保留原檔;rembg 透過 ONNX Runtime Web 執行 ONNX 模型,部分模型未提供。

正文

A lot of the best file tools are command-line programs. OxiPNG shrinks PNGs losslessly, SVGO minifies SVGs, rembg removes image backgrounds, and FFmpeg does everything to video. They're excellent, but each one asks you to install Rust, Node, Python or a native binary first. That's fine on your own machine, and annoying on a locked-down work laptop, a Chromebook, or when you just need to do one file.

I build a small site of browser tools, and over the last few weeks I moved these engines into pages that run entirely in the tab. Here is what that involved, and where the browser version is honestly worse.

1. OxiPNG: the easy one

OxiPNG is written in Rust, and the jSquash project already publishes it compiled to WebAssembly (it's the same build Squoosh used). The .wasm file is only about 164 KB, so I self-host it instead of loading it from a CDN.

The whole pipeline is: read the file into an ArrayBuffer, call optimise(data, level), and compare sizes. Two things I learned:

  • Return the original when it doesn't get smaller. A lot of PNGs people upload were already optimised by some tool. Re-encoding them can produce a file that is the same size or larger, so the page keeps the input in that case.
  • Levels above 4 are not worth it in a tab. The CLI has -o 0 to -o 6 plus max. In single-threaded WASM even level 4 can take several seconds on a 5-megapixel image, and the higher levels only get slower, so I expose 1–4.

The rough CLI equivalent of what the page runs is oxipng -o 4 input.png --out output.png.

2. SVGO: use the browser build

SVGO 4 ships a svgo/browser entry point that avoids the Node-only config loader. I run it with preset-default and multipass: true, and let the user pick the number precision. That is close to npx svgo --multipass --precision 3 input.svg.

One SVGO 4 detail that bit me: removeViewBox is no longer in preset-default. Keeping the viewBox is usually what you want for responsive SVGs, so I made removing it an explicit opt-in with a warning.

Also worth saying: rendering the result as an <img> preview is not a sanitiser. The preview doesn't execute scripts, but the file you download is still the SVG you uploaded, minus whitespace.

3. rembg: same models, different runtime

rembg is a Python tool that runs the U²-Net family of segmentation models. You can't run rembg itself in a browser, but you can run the same ONNX models with ONNX Runtime Web. I use a small browser port of rembg's pre- and post-processing.

Practical choices:

  • Bundle the small model, fetch the big one on demand. U²-NetP is about 4.7 MB and ships with the site, so the first run works without a third-party request. The full U²-Net model is much larger, so it's only downloaded from Hugging Face if the user switches to it.
  • ONNX Runtime's WASM files are the real weight. They are around 13 MB, which is more than the model. I serve them from the site and load them only when someone opens the tool.
  • Not every model is available. rembg's newer models (isnet, BiRefNet, SAM) aren't on the page. The sensitivity slider is a cheap pixel pass on the mask, not rembg's alpha matting.

4. FFmpeg: it works, but it's slow

ffmpeg.wasm really does run FFmpeg commands in the tab. The trick that made the biggest difference was trying a stream copy first. To mute a video, the page runs:

ffmpeg -i input.mp4 -c:v copy -an -movflags +faststart output.mp4

That doesn't re-encode anything, so it finishes almost instantly even in WASM. Only if the copy fails does it fall back to re-encoding with x264.

Everything else is limited by one fact: it's single-threaded. The multi-threaded FFmpeg core needs SharedArrayBuffer, which needs the page to be cross-origin isolated (COOP/COEP headers). Turning that on breaks a lot of ordinary third-party embeds, so for a general tool site I kept the single-threaded core. It's fine for a 30-second screen recording, and painful for a 10-minute 4K file. For big batches, native FFmpeg is the right tool, and the page says so.

5. Show the command, not just the button

The most useful change wasn't technical. Each tool page now shows the engine name, the exact version shipped, the licence, the equivalent command or code, and a short list of how it differs from the original. Developers trust a tool more when they can see that "PNG optimizer" means "OxiPNG level 4". It also helps people who will eventually move the job into a script.

What I'd tell someone doing the same

  1. Check whether a WASM build already exists (jSquash, ffmpeg.wasm, Tesseract.js, ONNX Runtime Web) before compiling anything yourself.
  2. Self-host the WASM if it's small, and lazy-load it only on the page that needs it.
  3. Always compare output size against input and keep the original if you didn't win.
  4. Be upfront about threads. Single-threaded WASM is noticeably slower than a native multithreaded CLI on CPU-heavy jobs, so say so instead of hiding it behind a spinner.
  5. Credit the projects properly. They did the hard part.

The pages are on onemilliontools.com, and there's an index of the engines at onemilliontools.com/open-source. They're free, and the files stay in your browser.

Disclosure: I build this site. I used AI assistance while drafting this post. The numbers above are from the site's own build (file sizes and the commands it runs), not benchmarks against other tools.

來源:DEV Community · dev.to