Drop a file, pick an output format, download it. Images, video, audio, documents and 3D models. Everything is decoded and re-encoded in the browser tab, so nothing gets uploaded.
- PNG to JPEG, WebP, AVIF
- JPEG to PNG, WebP, AVIF
- WebP to PNG, JPEG, AVIF
- AVIF to PNG, JPEG, WebP
- HEIC to JPEG, PNG, WebP, decoded through
heic2any - GIF to PNG, JPEG, WebP as a first frame, or to MP4 and WebM if animated
- BMP to PNG, JPEG, WebP
- SVG to PNG, JPEG, rasterised at 2x
- Any image to PDF
- MP4 to WebM, GIF
- WebM to MP4, GIF
- MOV to MP4, WebM
- MKV to MP4, WebM
- Any video to MP3 or WAV audio
- MP3 to WAV, OGG
- WAV to MP3, OGG
- FLAC to MP3, WAV, OGG
- OGG to MP3, WAV
- M4A to MP3, WAV
- PDF to PNG or JPEG, all pages stacked
- Several images into one PDF
- TXT and Markdown to PDF, paginated with wrapped text
- OBJ to GLB, STL, PLY
- STL to GLB, OBJ, PLY
- PLY to GLB, OBJ, STL
- glTF / GLB to OBJ, STL, PLY
- Collada (DAE) to GLB, OBJ, STL, PLY
- FBX to GLB, OBJ, STL, PLY
- 3MF to GLB, OBJ, STL, PLY
3D conversion covers mesh geometry. Materials survive into GLB and are dropped for the geometry-only formats. Animations, skeletons and Draco-compressed glTF are out of scope, and CAD formats like STEP and IGES aren't feasible in the browser.
bun install
bun run dev # http://localhost:3000
bun run lintThe pdfjs worker is vendored at public/pdf.worker.min.mjs. The ffmpeg WASM
core is fetched from a CDN at runtime and turned into a blob URL so it still
runs entirely client-side.
Next.js 16, TypeScript, Tailwind CSS 4 and shadcn/ui, with ffmpeg.wasm
(lazy-loaded, single-threaded core so COEP headers aren't needed) for video and
audio, Canvas and OffscreenCanvas for images, Web Audio plus
@breezystack/lamejs for audio encoding, pdf-lib and pdfjs-dist for PDF,
three.js for 3D, and heic2any for HEIC. Package manager is bun.
Conversion is local. Files are not uploaded, there is no analytics or tracking,
and localStorage holds nothing but a theme preference.
Import the repo on Vercel. Next.js is auto-detected, the defaults are right, and there are no environment variables. It works on any static host too.
Jeffrey Hamilton · GitHub · buy me a coffee