Skip to main content

ogacai

Pipeline de línea de comandos que convierte subtítulos automáticos de YouTube (.json3) en un artículo de blog en Markdown, usando DeepSeek (o, opcionalmente, Cloudflare Workers AI / Gemini) para la redacción.

Descripción

ogacai resuelve un problema puntual: pasar de un video de YouTube a un artículo publicable sin perder fidelidad al contenido hablado y sin depender de un proceso manual de transcripción y limpieza.

El flujo se divide en etapas separadas, cada una con una responsabilidad clara:

url de YouTube  →  .json3  →  raw.txt + clean.txt  →  IA  →  artículo.md validado + portada.png
   (fetch, opcional)              (procesar)              (procesar)    (generar + validar)      (portada, al final de `run` salvo --sin-portada)
  1. Obtención (ogacai/fetch.py, opcional): descarga el .json3 de subtítulos automáticos de un video de YouTube vía yt-dlp, sin descargar el video. Es la única etapa que depende de una herramienta externa — por eso yt-dlp es una dependencia opcional (pip install "ogacai[fetch]"), no obligatoria para quien ya tiene su propio .json3.
  2. Parseo y limpieza (ogacai/procesar.py): lee el .json3, reconstruye el texto hablado y produce dos versiones — una extracción fiel (raw) y una limpia (clean, sin repeticiones de "rolling captions" ni anotaciones tipo [música]). No llama a ninguna API; es reproducible y auditable.
  3. Generación (ogacai/deepseek.py / ogacai/workers_ai.py / ogacai/gemini.py + ogacai/prompt.py): envía el texto limpio a un proveedor de IA (DeepSeek por defecto; Cloudflare Workers AI o Gemini como alternativas, seleccionables con --proveedor) con un system prompt fijo. El modelo solo recibe texto y solo devuelve texto — sin tool-calling, sin acceso a disco.
  4. Validación (ogacai/validar.py): revisa que el artículo generado tenga la estructura esperada (front matter completo, tags coherentes, bloques de código bien cerrados). No valida fidelidad al contenido original — eso sigue siendo responsabilidad de una revisión humana.

Esta separación permite calibrar cada etapa por separado (por ejemplo, ajustar el prompt) sin gastar llamadas a la API mientras se depura el parseo.

Características

  • Parseo de .json3 de subtítulos automáticos de YouTube, con deduplicación de texto solapado por "rolling captions".
  • Limpieza opcional de muletillas comunes en español (eh, mmm, este, o sea, bueno, digo, entre otras) vía --sin-muletillas.
  • Eliminación de anotaciones entre corchetes ([música], [aplausos], etc.) que no son habla real.
  • Vista previa (preview) de qué palabras exactas quita la limpieza, sin necesidad de leer raw.txt/clean.txt completos a mano.
  • Generación de artículos en Markdown vía DeepSeek, Cloudflare Workers AI o Gemini (--proveedor deepseek|workers-ai|gemini, default deepseek), con un system prompt fijo que distingue entre artículo narrativo (caso de estudio) y artículo explicativo/técnico, y reintentos con backoff ante fallas transitorias de red.
  • Validación estructural del front matter (title, description, date, image, imageAlt, tags) y de los tags según el tipo de artículo.
  • Resolución de configuración (API key y carpeta de salida) por variable de entorno o archivo config.toml.
  • Pipeline completo (run) con modo --dry-run para revisar el resultado antes de escribir el archivo final, y generación de la portada OpenGraph como paso final (salvo --sin-portada).
  • Sin dependencia de binarios compilados: corre igual en Termux, Linux o macOS usando el resolvedor DNS y el almacén de certificados del sistema (vía requests).

Requisitos

  • Python 3.9 o superior (usa tomllib de la librería estándar en 3.11+; en versiones anteriores se instala tomli como dependencia).
  • Dependencia en tiempo de ejecución: requests (>=2.25).
  • Una API key de DeepSeek (solo necesaria para los subcomandos que llaman al modelo, y solo si usás el proveedor por defecto). Si preferís otro proveedor, necesitás en cambio credenciales de Cloudflare Workers AI (account ID + API token) o de Gemini (una API key) — ver "Configurar credenciales" más abajo.
  • Un archivo .json3 de subtítulos automáticos de un video de YouTube. ogacai puede descargarlo por vos con ogacai fetch (ver más abajo, requiere instalar el extra fetch), o podés obtenerlo por tu cuenta con yt-dlp y pasárselo directamente a ogacai procesar/ogacai run.
  • Opcional: yt-dlp (>=2024.1), solo si querés usar ogacai fetch. Se instala con pip install "ogacai[fetch]".

Instalación

Termux:

pkg update
pkg install python
pip install .
ogacai --help

Linux o macOS:

python3 -m venv .venv
source .venv/bin/activate
pip install .
ogacai --help

Sin instalar el paquete (para ejecutar directamente desde el código fuente):

pip install -r requirements.txt
python -m ogacai --help

Para usar ogacai fetch (descargar el .json3 vía yt-dlp), instalá el extra correspondiente:

pip install "ogacai[fetch]"

Configurar credenciales de los proveedores de IA

ogacai generar/ogacai run usan DeepSeek por defecto (--proveedor deepseek), pero podés elegir Cloudflare Workers AI (--proveedor workers-ai) o Gemini (--proveedor gemini) en su lugar. Solo hace falta configurar las credenciales del proveedor que realmente vayas a usar.

DeepSeek (default, una sola credencial), en orden de prioridad (la primera gana si ambas están definidas):

export DEEPSEEK_API_KEY="tu-key-aqui"

o de forma persistente:

mkdir -p ~/.config/ogacai
cat > ~/.config/ogacai/config.toml << 'EOF'
api_key = "tu-key-aqui"
output_dir = "/ruta/a/tu-repo-blog/src/content/blog"
EOF

output_dir es opcional: define la carpeta por defecto donde ogacai run escribe el artículo final si no se pasa --output-dir.

Cloudflare Workers AI (--proveedor workers-ai, requiere DOS credenciales: account ID + API token):

export WORKERS_AI_ACCOUNT_ID="tu-account-id"
export WORKERS_AI_API_TOKEN="tu-api-token"

o de forma persistente:

ogacai config set workers_ai.account_id "tu-account-id"
ogacai config set workers_ai.api_token "tu-api-token"

Gemini (--proveedor gemini, una sola credencial, más un modelo opcional):

export GEMINI_API_KEY="tu-key-aqui"

o de forma persistente:

ogacai config set gemini.api_key "tu-key-aqui"
ogacai config set gemini.model "gemini-3.5-flash-lite"   # opcional; ver nota abajo

gemini.model es opcional: si no se configura, se usa gemini-3.5-flash-lite (el default del cliente). El catálogo de modelos de Gemini rota rápido (versiones previas dejan de estar disponibles para cuentas nuevas), así que conviene poder cambiarlo sin tocar código si Google retira el modelo actual.

ogacai config show muestra la configuración resuelta, con las API keys/tokens enmascarados (solo se ven los últimos 4 caracteres).

Uso

Ejemplo mínimo, de principio a fin:

# 0. (Opcional) Descargar el .json3 directo desde una URL de YouTube
ogacai fetch "https://youtu.be/tu-video" --salida-dir /tmp/prueba
# -> imprime "Listo: /tmp/prueba/<video_id>.es.json3"

# 1. Parsear el .json3 (gratis, no llama a ninguna API)
ogacai procesar /tmp/prueba/<video_id>.es.json3 --salida-dir /tmp/prueba

# 2. (Opcional) Revisar qué quitó la limpieza antes de gastar la llamada a DeepSeek
ogacai preview /tmp/prueba/<video_id>.es.json3

# 3. Generar el artículo con DeepSeek (default) -- usá --proveedor workers-ai o --proveedor gemini para otro proveedor
export DEEPSEEK_API_KEY="tu-key-aqui"
ogacai generar /tmp/prueba/transcripcion_clean.txt --output /tmp/prueba/articulo.md

# 4. Validar la estructura del artículo generado
ogacai validar /tmp/prueba/articulo.md

Pipeline completo en un solo paso, primero en modo de prueba:

ogacai run mi-video.json3 --dry-run

Y, una vez conforme con el resultado, la corrida que escribe el archivo final:

ogacai run mi-video.json3 --output-dir /ruta/a/tu-repo-blog/src/content/blog

CLI

ogacai --help
usage: ogacai [-h] [-V] {fetch,procesar,preview,generar,validar,run} ...
Subcomando Qué hace
fetch Etapa 0, opcional: descarga el .json3 de subtítulos automáticos de una URL de YouTube vía yt-dlp, sin descargar el video.
procesar Etapas 1-2: .json3transcripcion_raw.txt + transcripcion_clean.txt. No llama a ninguna API.
preview Corre las etapas 1-2 en memoria (sin escribir archivos) y muestra qué palabras exactas quitó la limpieza.
generar Etapa 3: llama a un proveedor de IA (--proveedor deepseek|workers-ai|gemini, default deepseek) con un .txt ya limpio y devuelve el artículo por salida estándar (o a un archivo con --output).
validar Valida estructuralmente un artículo .md/.mdx ya generado.
run Pipeline completo: procesargenerarvalidar, con escritura del artículo final y generación de la portada (paso 5, salvo --sin-portada).

ogacai fetch

ogacai fetch [-h] [--lang LANG] [--salida-dir SALIDA_DIR] url
ogacai fetch "https://youtu.be/tu-video" --lang es-orig --salida-dir /tmp/prueba
  • url: URL del video de YouTube.
  • --lang: pista de subtítulos automáticos a descargar (por defecto es). es-orig (español sin traducción automática) suele ser preferible cuando el video la tiene.
  • --salida-dir: carpeta donde escribir el .json3 (por defecto, el directorio actual).

Requiere el extra fetch instalado (pip install "ogacai[fetch]"). No descarga el video, solo los subtítulos. Si el video no tiene la pista pedida, informa qué pistas automáticas sí están disponibles en vez de fallar en silencio.

ogacai procesar

ogacai procesar [-h] [--sin-muletillas] [--salida-dir SALIDA_DIR] archivo_json3
ogacai procesar mi-video.json3 --sin-muletillas --salida-dir /tmp/prueba
  • archivo_json3: ruta al archivo .json3 de subtítulos.
  • --sin-muletillas: elimina muletillas comunes en español además de la limpieza básica.
  • --salida-dir: carpeta de salida (por defecto, el directorio actual).

ogacai preview

ogacai preview [-h] [--sin-muletillas] archivo_json3
ogacai preview mi-video.json3 --sin-muletillas

Corre las etapas 1-2 en memoria (no escribe raw.txt/clean.txt) y muestra, con un diff por palabras (difflib, sin dependencias externas), exactamente qué se quitó entre raw y clean. Pensado para confiar en la limpieza antes de gastar una llamada a DeepSeek.

ogacai generar

ogacai generar [-h] [--proveedor {deepseek,workers-ai,gemini}] [--output OUTPUT] archivo_clean_txt
ogacai generar /tmp/prueba/transcripcion_clean.txt --output /tmp/prueba/articulo.md
ogacai generar /tmp/prueba/transcripcion_clean.txt --proveedor gemini --output /tmp/prueba/articulo.md
  • archivo_clean_txt: ruta al .txt limpio.
  • --proveedor: proveedor de IA a usar (default deepseek). Requiere las credenciales correspondientes ya configuradas (ver "Configurar credenciales de los proveedores de IA" más arriba): DEEPSEEK_API_KEY para deepseek, workers_ai.account_id/workers_ai.api_token para workers-ai, GEMINI_API_KEY/gemini.api_key para gemini.
  • --output OUTPUT: archivo donde escribir el artículo generado. Sin este flag, el resultado se imprime por salida estándar (hay que redirigirlo con > para guardarlo). Reintenta automáticamente (con backoff) ante timeouts o errores de red — no ante errores ya devueltos por el servidor (autenticación, límite de uso, etc.).

ogacai validar

ogacai validar [-h] archivo_articulo
ogacai validar /tmp/prueba/articulo.md

Revisa front matter completo, coherencia de tags y bloques de código balanceados. No confirma fidelidad al contenido original.

ogacai run

ogacai run [-h] [--sin-muletillas] [--proveedor {deepseek,workers-ai,gemini}] [--output-dir OUTPUT_DIR] [--dry-run] [--sin-portada] archivo_json3
ogacai run mi-video.json3 --output-dir /ruta/a/tu-repo-blog/src/content/blog
ogacai run mi-video.json3 --proveedor gemini --output-dir /ruta/a/tu-repo-blog/src/content/blog
  • --sin-muletillas: igual que en procesar.
  • --proveedor: igual que en generar (default deepseek).
  • --output-dir: carpeta de salida final (si no se pasa, usa config.toml o el directorio actual).
  • --dry-run: corre todo el pipeline pero solo imprime el resultado, sin escribir el archivo.
  • --sin-portada: no genera la portada OpenGraph al final. Por defecto, run la genera si la sección [portada] de la config está seteada (el extra ogacai[portada] sigue siendo opcional: si falta, el error se anota al final del flujo y run devuelve código 1).

El nombre del archivo final se deriva del campo title del front matter generado (slug en minúsculas, sin tildes, separado por guiones). Si no se puede extraer un título, se usa articulo-sin-titulo.md. Con la portada habilitada, run además escribe {assets_dir}/{slug}.png y corrige el campo image del front matter para que apunte a ese archivo (misma lógica que el subcomando portada, vía portada.generar_desde_articulo).

Salida / JSON

ogacai no genera JSON de salida: parte de un JSON de entrada, el .json3 de subtítulos que ogacai procesar/ogacai run esperan recibir (obtenido con ogacai fetch o por tu cuenta con yt-dlp). El parseo (ogacai/procesar.py) valida que el archivo sea JSON válido y que tenga la clave events; de lo contrario, corta con un error explícito.

Estructura real de un .json3 (ejemplo simplificado):

{
  "wireMagic": "pb3",
  "pens": [],
  "wsWinStyles": [],
  "wpWinPositions": [],
  "events": [
    {
      "tStartMs": 0,
      "dDurationMs": 801784,
      "id": 1,
      "wpWinPosId": 1,
      "wsWinStyleId": 1
    },
    {
      "tStartMs": 3840,
      "dDurationMs": 4079,
      "wWinId": 1,
      "segs": [
        { "utf8": "desarrolladores.", "acAsrConf": 0 },
        { "utf8": " Y", "tOffsetMs": 800, "acAsrConf": 0 }
      ]
    }
  ]
}

Campos relevantes para ogacai:

  • events: lista de eventos de subtítulo. Es la única clave que el parser exige.
  • segs: dentro de cada evento, la lista de segmentos de texto. Solo los eventos que tienen segs aportan contenido — se concatena el campo utf8 de cada segmento para reconstruir el texto hablado. Eventos sin segs (como marcadores de posición o estilo) se ignoran.
  • tStartMs / dDurationMs / tOffsetMs: timestamps que el parser lee pero que, por ahora, no se usan en ninguna salida.

A partir de ese .json3, ogacai procesar produce dos archivos de texto plano (no JSON): transcripcion_raw.txt y transcripcion_clean.txt.

Estructura del proyecto

ogacai/
├── cli.py       # Punto de entrada de la CLI (argparse): subcomandos fetch/procesar/preview/generar/validar/run
├── fetch.py     # Etapa 0 (opcional): descarga el .json3 vía yt-dlp
├── procesar.py  # Etapas 1-2: parseo del .json3 y limpieza determinística, sin LLM
├── prompt.py    # System prompt fijo usado en la etapa de generación
├── deepseek.py  # Cliente HTTP a la API de DeepSeek (usa requests), con reintentos ante fallas de red
├── workers_ai.py # Cliente HTTP a Cloudflare Workers AI, proveedor alternativo (mismo contrato que deepseek.py)
├── gemini.py    # Cliente HTTP a Gemini (endpoint interactions), proveedor alternativo (mismo contrato que deepseek.py)
├── normalizar.py # Normalización de salida compartida entre proveedores (ej. quitar fence externo ```yaml)
├── config.py    # Resolución de credenciales de cada proveedor y de la carpeta de salida (env var o config.toml)
└── validar.py   # Validación estructural del artículo generado
tests/           # Suite de tests (pytest) y fixtures de .json3 reales/mínimos
.github/workflows/ci.yml  # CI: pytest, ruff y mypy en push/PR
pyproject.toml   # Metadata del paquete, entry point y el extra opcional [fetch] (yt-dlp)
requirements.txt # Dependencias para ejecutar sin instalar el paquete

Documentación

  • GETTING_STARTED.md: guía paso a paso orientada a quien nunca usó la CLI, con ejemplos de instalación, uso de cada subcomando, casos de uso completos y solución de errores comunes.

Desarrollo

El proyecto tiene una suite de tests (pytest), lint (ruff) y type checking (mypy), corridos automáticamente en CI (.github/workflows/ci.yml) en cada push/PR.

python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

pytest -v          # tests
ruff check .        # lint
mypy ogacai          # type checking

Con esta instalación en modo desarrollo, los cambios en ogacai/ se reflejan de inmediato al ejecutar python -m ogacai o pytest. La carpeta tests/fixtures/ incluye un .json3 real y uno mínimo hecho a mano, usados por los tests de procesar.py. Los tests de fetch.py mockean yt-dlp por completo — no hacen llamadas de red reales. La carpeta prueba/ contiene una transcripción y un artículo de ejemplo ya generados, útiles como referencia rápida sin tener que correr el pipeline completo de nuevo.

Contribuciones

El repositorio no define un proceso formal de contribución. Para proponer un cambio, el camino directo es abrir un issue o un pull request describiendo el problema o la mejora concreta.

Licencia

MIT, según lo declarado en pyproject.toml. El repositorio no incluye actualmente un archivo LICENSE independiente.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ogacai-0.1.0.tar.gz (57.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ogacai-0.1.0-py3-none-any.whl (45.0 kB view details)

Uploaded Python 3

File details

Details for the file ogacai-0.1.0.tar.gz.

File metadata

  • Download URL: ogacai-0.1.0.tar.gz
  • Upload date:
  • Size: 57.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for ogacai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fdc78d8101fdd330de7218ddb7fdd4cdeb05655a8ad5d764a4dedee243683472
MD5 03fb27bd7b0ca1d4a10014f552362997
BLAKE2b-256 12a1224fe533419e87c7fac178ca9fc74f60344b2d3d234d8086dd2e9b717466

See more details on using hashes here.

File details

Details for the file ogacai-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ogacai-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 45.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for ogacai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 368abe4ff5ec211898133e89ba1da889b0ec04e325879b5981108abe9c5f6da3
MD5 7a85e13c1c517873ca1ca33e5db4f02b
BLAKE2b-256 854e4722743e8d55fc80e7a2106cbc7392489cab598b260c5a2e6c53baf4e7a0

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.2

2 files

0.2.1

2 files

0.2.0

2 files

0.1.1

2 files

This release

0.1.0 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page