One command. Any format. OmniConvert takes a source file and a target format and figures out the best conversion path — even if no direct converter exists. It models file formats as nodes and converters as edges in a directed graph, then runs Breadth-First Search to find the shortest chain.
$ omniconvert convert events.root events.json
events.root → events.json (root → csv → json)
⠿ Converting ━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:01
✓ Done: events.jsonNo direct root → json converter exists, yet OmniConvert found the shortest path automatically. This chaining works across any set of registered converters — graph-based, infinitely extensible.
🖥️ Desktop GUI — Double-click to launch
Double-click OmniConvert.command on macOS (first run sets up the environment). The GUI walks you through three steps:
- Pick source file via native file dialog
- Choose target format — the UI shows reachable formats and their conversion chains
- Convert with a live progress bar
make gui # or: omniconvert gui# Core + dev tools (CSV ↔ JSON work out of the box)
make install
# Everything: ROOT, audio, and GUI
make install-allOr pick your extras with pip:
pip install -e "." # core only
pip install -e ".[extended,ocr]" # + extended & ocr converters
pip install -e ".[gui]" # + desktop GUI
pip install -e ".[all]" # everything
⚠️ MP3 → WAV requiresffmpegon your system:brew install ffmpeg(macOS),apt install ffmpeg(Linux).
| Command | What it does |
|---|---|
omniconvert convert data.csv data.json |
Simple conversion (formats auto-detected) |
omniconvert convert events.root events.json |
Automatic multi-step chaining |
omniconvert convert export.dat out.json --from csv --to json |
Force formats when extension doesn't match |
omniconvert convert file.root file.json --via csv |
Force a specific intermediate format |
omniconvert convert --batch "data/*.csv" --to json |
⚡️ Ultra-fast Concurrent Batch Processing |
omniconvert convert book.pdf book.md --to md-sci |
🔬 Scientific OCR (Deep Learning based equations) |
omniconvert formats |
List all registered converters |
omniconvert path root json |
Dry-run: shows the shortest conversion path |
python -m omni_convert ... |
Use as a Python module |
src/omni_convert/
├── cli.py # Typer CLI — 4 commands: convert, formats, path, gui
├── core/
│ ├── converter.py # ABC Converter + ConversionError, MissingDependencyError
│ ├── registry.py # Dynamic registry with pkgutil auto-discovery
│ └── pipeline.py # BFS shortest-path + Pipeline chained execution
├── converters/
│ ├── data/ # csv↔json, root→csv
│ └── audio/ # mp3→wav
└── gui/
├── api.py # Python ↔ JS bridge (testable without a window!)
├── app.py # pywebview native desktop window
└── static/index.html # Self-contained HTML/CSS/JS single-page app
| Decision | Why |
|---|---|
| Graph-based chaining | Formats = nodes, converters = edges. BFS guarantees shortest path. |
| Dynamic registry | @register decorator + pkgutil.walk_packages auto-discovers converters. Plug-and-play from external packages. |
| Lazy dependency imports | uproot, pydub, pywebview imported inside convert(), not at module level. Registry works without them; missing deps produce clear pip install hints. |
| Progress callbacks | Each converter reports 0.0 → 1.0. CLI renders via Rich progress bars; GUI pushes to JavaScript. |
| Testable GUI | GuiApi never imports pywebview globally. Tests inject a fake window to verify API logic without a real GUI. |
graph LR
A[📁 data.root] -->|RootToCsv| B[📄 temp.csv]
B -->|CsvToJson| C[📄 temp.json]
C --> D[✅ output.json]
style A fill:#f9f,stroke:#333
style D fill:#9f9,stroke:#333
- 🧠 Auto-Routing Core: Dijkstra-based graph search that figures out multi-step conversions on its own.
- ⚡️ Blazing Fast Batching: Converts hundreds of files in parallel via ThreadPool executors, fully utilizing your CPU cores while limiting RAM intelligently for heavy ML models.
- 🎨 Premium Terminal UI: Built with
rich, featuring beautiful progress bars, dynamic spinners, and async heartbeats so you always know exactly what's processing. - 🧩 Pluggable Architecture: Zero-friction plugins. Just drop a file in
converters/with the@registerdecorator and OmniConvert does the rest. - 🔬 Deep Learning OCR: Uses
marker-pdfandpix2texfor high-fidelity conversion of scientific papers directly to LaTeX-embedded Markdown.
| # | Source → Target | Class | Dependencies |
|---|---|---|---|
| 1 | csv → json | CsvToJson |
stdlib |
| 2 | json → csv | JsonToCsv |
stdlib |
| 3 | root → csv | RootToCsv |
uproot, numpy |
| 4 | mp3 → wav | Mp3ToWav |
pydub + system ffmpeg |
Add a converter in 30 seconds:
from omni_convert.core import Converter, register
@register
class YamlToJson(Converter):
source_format = "yaml"
target_format = "json"
def convert(self, input_path, output_path, progress):
import yaml, json # heavy imports go here
with open(input_path) as f:
data = yaml.safe_load(f)
with open(output_path, "w") as f:
json.dump(data, f, indent=2)
progress(1.0)Place it in src/omni_convert/converters/ and it auto-discovers. From an external package, call registry.discover("my_package.converters").
💡 Ideas for expansion:
| Area | Converters | Notes |
|---|---|---|
| 🖼️ Images | png↔jpg, webp↔avif | pillow or opencv |
| 🎥 Video | mp4↔gif, mov↔webm | ffmpeg-python |
| 📄 Documents | md↔html, pdf↔docx | markdown, pdfkit |
| ⚡ Performance | Rust-backed via PyO3 | For compute-heavy transforms |
| 🌐 Web API | Server mode | FastAPI + streaming |
Development:
make test # pytest (missing extras → skipped gracefully)
make test-fast # pytest in parallel with xdist
make lint # ruff check + format --check
make format # auto-formatFull design doc: docs/superpowers/specs/2026-06-12-omniconvert-design.md
Un comando. Cualquier formato. OmniConvert toma un archivo de origen y un formato de destino y encuentra la mejor ruta de conversión — incluso si no existe un conversor directo. Modela los formatos como nodos y los conversores como aristas en un grafo dirigido, luego ejecuta Búsqueda en Anchura (BFS) para hallar la cadena más corta.
$ omniconvert convert eventos.root eventos.json
eventos.root → eventos.json (root → csv → json)
⠿ Convirtiendo ━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:01
✓ Conversión completada: eventos.jsonNo existe un conversor directo root → json, pero OmniConvert encontró la ruta más corta automáticamente. Este encadenamiento funciona sobre cualquier conjunto de conversores registrados — basado en grafos, infinitamente extensible.
🖥️ Interfaz gráfica — Doble clic para abrir
Haz doble clic en OmniConvert.command en macOS (el primer inicio configura el entorno). La interfaz te guía en tres pasos:
- Elige archivo de origen con el diálogo nativo del sistema
- Elige formato de destino — la UI muestra formatos alcanzables y sus cadenas
- Convierte con barra de progreso en vivo
make gui # o: omniconvert gui# Core + herramientas de desarrollo (CSV ↔ JSON funcionan ya)
make install
# Todo: ROOT, audio y GUI
make install-allO elige tus extras con pip:
pip install -e "." # solo core
pip install -e ".[extended,ocr]" # + conversores extendidos y ocr
pip install -e ".[gui]" # + interfaz gráfica
pip install -e ".[all]" # todo
⚠️ MP3 → WAV requiereffmpegen el sistema:brew install ffmpeg(macOS),apt install ffmpeg(Linux).
| Comando | Acción |
|---|---|
omniconvert convert data.csv data.json |
Conversión simple (detecta formatos automáticamente) |
omniconvert convert events.root events.json |
Encadenamiento automático de múltiples pasos |
omniconvert convert export.dat out.json --from csv --to json |
Fuerza formatos si la extensión no concuerda |
omniconvert convert file.root file.json --via csv |
Obliga a pasar por un formato intermedio específico |
omniconvert convert --batch "data/*.csv" --to json |
⚡️ Procesamiento concurrente ultra rápido por lotes |
omniconvert convert book.pdf book.md --to md-sci |
🔬 OCR Científico (Extrae ecuaciones mediante Deep Learning) |
omniconvert formats |
Muestra la lista de todos los conversores registrados |
omniconvert path root json |
Muestra la ruta de conversión óptima sin ejecutarla |
OmniConvert no usa conversores monolíticos como "docx to epub". Define módulos pequeños y reusables.
- 🧠 Enrutamiento Automático: Algoritmo de búsqueda de grafos (Dijkstra) que encuentra el mejor camino de conversión.
- ⚡️ Batching Ultra Rápido: Convierte cientos de archivos en paralelo a través de ThreadPools, aprovechando tu CPU y limitando inteligentemente la RAM en modelos de ML pesados.
- 🎨 UI de Terminal (TUI) Premium: Interfaz moderna desarrollada con
richque presenta barras de progreso asíncronas, spinners dinámicos y "heartbeats" para saber exactamente qué ocurre. - 🧩 Arquitectura de Plugins: Agregar un conversor es tan fácil como crear un archivo con
@register. - 🔬 OCR con IA Avanzada: Integra
marker-pdfypix2texpara conversiones científicas pesadas, rescatando ecuaciones de papers y convirtiéndolas en LaTeX perfecto.
| Decisión | Por Qué |
|---|---|
| Encadenamiento por grafos | Formatos = nodos, conversores = aristas. BFS garantiza camino más corto. |
| Registro dinámico | Decorador @register + pkgutil.walk_packages auto-descubre conversores. Plug-and-play desde paquetes externos. |
| Imports perezosos | uproot, pydub, pywebview se importan dentro de convert(), no a nivel de módulo. El registro funciona sin ellos; las dependencias faltantes muestran instrucciones pip install claras. |
| Progreso por callback | Cada conversor reporta 0.0 → 1.0. CLI renderiza con barras Rich; GUI lo empuja a JavaScript. |
| GUI testeable | GuiApi nunca importa pywebview globalmente. Los tests inyectan una ventana falsa para verificar la lógica sin GUI real. |
graph LR
A[📁 data.root] -->|RootToCsv| B[📄 temp.csv]
B -->|CsvToJson| C[📄 temp.json]
C --> D[✅ output.json]
style A fill:#f9f,stroke:#333
style D fill:#9f9,stroke:#333
| # | Origen → Destino | Clase | Dependencias |
|---|---|---|---|
| 1 | csv → json | CsvToJson |
stdlib |
| 2 | json → csv | JsonToCsv |
stdlib |
| 3 | root → csv | RootToCsv |
uproot, numpy |
| 4 | mp3 → wav | Mp3ToWav |
pydub + ffmpeg del sistema |
Añade un conversor en 30 segundos:
from omni_convert.core import Converter, register
@register
class YamlToJson(Converter):
source_format = "yaml"
target_format = "json"
def convert(self, input_path, output_path, progress):
import yaml, json # imports pesados van aquí
with open(input_path) as f:
data = yaml.safe_load(f)
with open(output_path, "w") as f:
json.dump(data, f, indent=2)
progress(1.0)Colócalo en src/omni_convert/converters/ y se auto-descubre. Desde un paquete externo, llama a registry.discover("mi_paquete.converters").
💡 Ideas de expansión:
| Área | Conversores | Notas |
|---|---|---|
| 🖼️ Imágenes | png↔jpg, webp↔avif | pillow o opencv |
| 🎥 Video | mp4↔gif, mov↔webm | ffmpeg-python |
| 📄 Documentos | md↔html, pdf↔docx | markdown, pdfkit |
| ⚡ Rendimiento | Backend Rust vía PyO3 | Para transformaciones intensivas |
| 🌐 API Web | Modo servidor | FastAPI + streaming |
Desarrollo:
make test # pytest (extras faltantes → omitidos)
make test-fast # pytest en paralelo con xdist
make lint # ruff check + format --check
make format # auto-formatoDocumento de diseño completo: docs/superpowers/specs/2026-06-12-omniconvert-design.md
MIT © 2026 Jose Labarca
Parte del Pharos Project — infraestructura científica y educativa sin barreras de entrada. · José Labarca Baeza