p2r3 / convert
- четверг, 19 февраля 2026 г. в 00:00:05
Truly universal online file converter
Truly universal online file converter.
Many online file conversion tools are boring and insecure. They only allow conversion between two formats in the same medium (images to images, videos to videos, etc.), and they require that you upload your files to some server.
This is not just terrible for privacy, it's also incredibly lame. What if you really need to convert an AVI video to a PDF document? Try to find an online tool for that, I dare you.
Convert.to.it aims to be a tool that "just works". You're almost guaranteed to get an output - perhaps not always the one you expected, but it'll try its best to not leave you hanging.
For a semi-technical overview of this tool, check out the video: https://youtu.be/btUbcsTbVA8
Ever since the YouTube video released, we've been getting spammed with issues suggesting the addition of all kinds of niche file formats. To keep things organized, I've decided to specify what counts as a valid issue and what doesn't.
Important
SIMPLY ASKING FOR A FILE FORMAT TO BE ADDED IS NOT A MEANINGFUL ISSUE!
There are thousands of file formats out there. It can take hours to add support for just one. The math is simple - we can't possibly support every single file. As such, simply listing your favorite file formats is not helpful. We already know that there are formats we don't support, we don't need tickets to tell us that.
When suggesting a file format, you must at minimum:
If this seems like a lot, please remember - a developer will have to do 100x more work to actually implement the format. Doing a bit of research not only saves them precious time, it also weeds out "unserious" proposals that would only bloat our to-do list.
If you're submitting a bug report, you only need to do step 1 - check if the problem isn't already reported by someone else. Bug reports are generally quite important otherwise.
Though please note, "converting X to Y doesn't work" is not a bug report. However, "converting X to Y works but not how I expected" likely is a bug report.
git clone --recursive https://github.com/p2r3/convert for that. Omitting submodules will leave you missing a few dependencies.bun install to install dependencies.bunx vite to start the development server.The following steps are optional, but recommended for performance:
When you first open the page, it'll take a while to generate the list of supported formats for each tool. If you open the console, you'll see it complaining a bunch about missing caches.
After this is done (indicated by a Built initial format list message in the console), use printSupportedFormatCache() to get a JSON string with the cache data. You can then save this string to cache.json to skip that loading screen on startup.
Docker compose files live in the docker/ directory, so run compose with -f from the repository root:
docker compose -f docker/docker-compose.yml up -dAlternatively download the docker-compose.yml separately and start it by executing docker compose up -d in the same directory.
This runs the container on http://localhost:8080/convert/.
Use the override file to build the image locally:
docker compose -f docker/docker-compose.yml -f docker/docker-compose.override.yml up --build -dThe first Docker build is expected to be slow because Chromium and related system packages are installed in the build stage (needed for puppeteer in buildCache.js). Later builds are usually much faster due to Docker layer caching.
The best way to contribute is by adding support for new file formats (duh). Here's how that works:
Each "tool" used for conversion has to be normalized to a standard form - effectively a "wrapper" that abstracts away the internal processes. These wrappers are available in src/handlers.
Below is a super barebones handler that does absolutely nothing. You can use this as a starting point for adding a new format:
// file: dummy.ts
import type { FileData, FileFormat, FormatHandler } from "../FormatHandler.ts";
import CommonFormats from "src/CommonFormats.ts";
class dummyHandler implements FormatHandler {
public name: string = "dummy";
public supportedFormats?: FileFormat[];
public ready: boolean = false;
async init () {
this.supportedFormats = [
// Example PNG format, with both input and output disabled
CommonFormats.PNG.builder("png")
.markLossless()
// .allowFrom()
// .allowTo()
];
this.ready = true;
}
async doConvert (
inputFiles: FileData[],
inputFormat: FileFormat,
outputFormat: FileFormat
): Promise<FileData[]> {
const outputFiles: FileData[] = [];
return outputFiles;
}
}
export default dummyHandler;For more details on how all of these components work, refer to the doc comments in src/FormatHandler.ts. You can also take a look at existing handlers to get a more practical example.
There are a few additional things that I want to point out in particular:
dummy, then the class should be called dummyHandler, and the file should be called dummy.ts.new Uint8Array().If your tool requires an external dependency (which it likely does), there are currently two well-established ways of going about this:
npm package, just install it to the project like you normally would.Please try to avoid CDNs (Content Delivery Networks). They're really cool on paper, but they don't work well with TypeScript, and each one introduces a tiny bit of instability. For a project that leans heavily on external dependencies, those bits of instability can add up fast.
/convert/wasm/. Do not link to node_modules.