Skip to content

josuebustosn/gemini-transcribe

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gemini-transcribe

Transcribe cualquier audio o video en segundos desde Claude Code, sin pagar por transcripción.

Una skill que convierte archivos de voz (WhatsApp PTTs, llamadas, reuniones, podcasts) en Markdown estructurado con timestamps e identificación de hablantes, usando la API de Google Gemini. Reemplazo directo de ElevenLabs Scribe, AssemblyAI o Whisper para quien ya paga Gemini.

Built for Claude Code License: MIT Version Powered by Gemini Español


El problema que resuelve

Cualquiera que reciba audios de WhatsApp del equipo, llamadas grabadas, o notas de voz pasa horas escuchándolas o pagando un servicio externo para transcribirlas.

Las opciones actuales tienen problemas:

  • ElevenLabs Scribe — ahora es de pago.
  • Whisper local — buena calidad, pero requiere instalar el modelo, configurar GPU, y los timestamps son por palabra (no por turno de habla).
  • AssemblyAI / Deepgram — funciona, pero es un servicio aparte que paga.
  • Pegar el audio a un chat de IA — funciona para uno, pero no escala a 5 audios, ni produce output estructurado, ni mantiene timestamps fiables.

Si ya pagas la API de Gemini para otra cosa, ya tienes un transcriptor de clase mundial sin costo extra. Esta skill expone esa capacidad como un comando único en Claude Code.


¿Qué hace?

Le pasas uno o varios archivos de audio/video. Te devuelve un Markdown estructurado por archivo:

  • Idioma detectado automáticamente.
  • Duración estimada y número de hablantes.
  • Resumen en una línea + temas del audio.
  • Transcripción segmentada (4-15s por segmento) con timestamps [MM:SS] y etiqueta Hablante 1 / Hablante 2 / ....
  • Notas del transcriptor cuando hay ruido, idioma mixto o palabras inaudibles.

Formatos soportados: .ogg .opus .mp3 .m4a .wav .flac .aac .webm .mp4 .mov .mpeg .mpga.


Before / After

Before — sin la skill

Recibes 3 audios de WhatsApp del equipo (3.5 min en total). Para procesarlos con tu IA:

  1. Subes uno por uno a ElevenLabs/Whisper online.
  2. Esperas la transcripción (sin estructura).
  3. Copias-pegas a un chat.
  4. Le pides que separe por hablantes y por temas.
  5. Pierdes 10-15 minutos por cada lote.

After — con gemini-transcribe

Le dices a Claude Code:

"Transcribe estos audios: C:\audios\nota1.ogg C:\audios\nota2.ogg C:\audios\nota3.ogg"

Claude detecta los paths, invoca la skill, y en ~12 segundos paralelos te devuelve:

audios/
├── nota1.ogg
├── nota1.ogg.transcripcion.md   ← generado
├── nota2.ogg
├── nota2.ogg.transcripcion.md   ← generado
├── nota3.ogg
└── nota3.ogg.transcripcion.md   ← generado

Cada .transcripcion.md con esta estructura:

# Transcripción — nota1.ogg

_Generado el 2026-05-25 22:37 con `gemini-3.5-flash`._

---

## nota1.ogg

- **Idioma:** es
- **Duración estimada:** ~217 s (3m 37s)
- **Hablantes detectados:** 2
- **Resumen:** Revisión de PR sobre flujo de registro/login, proponiendo unificar la UI.
- **Temas:** Pull Request, Frontend, Registro, UX

### Transcripción

**[00:00] Hablante 1:** Hola bro, ¿cómo estás? Ya revisé el PR sobre el tema de la... del registro.

**[00:11] Hablante 1:** Hay un par de cositas y es que develop ya tenía esa idea integrada.

**[00:23] Hablante 2:** Eh, espera, pero entonces el recovery password no estaba bugueado?
...

Y si quieres un MD unificado con índice y todas las transcripciones:

python ~/.claude/skills/transcribir/transcribe.py --combined ./resumen.md ./audios/*.ogg

Instalación

Prerequisitos

  1. Python 3.10+ instalado.
  2. API key de Google Gemini — gratuita en aistudio.google.com/apikey.
  3. Claude Code instalado.

1. Clonar el repo

git clone https://github.com/josuebustosn/gemini-transcribe.git
cd gemini-transcribe

2. Instalar la dependencia Python

pip install -r requirements.txt

3. Copiar la skill a ~/.claude/skills/

Linux / macOS / Git Bash:

mkdir -p ~/.claude/skills
cp -r skills/transcribir ~/.claude/skills/

PowerShell (Windows):

New-Item -ItemType Directory -Force -Path "$HOME\.claude\skills" | Out-Null
Copy-Item -Recurse skills\transcribir "$HOME\.claude\skills\"

Tip

Si Claude Code está haciendo esto por ti, es una copia simple de directorio. Después de copiar, dile al usuario que reinicie Claude Code para que escanee la nueva skill.

4. Setear la GEMINI_API_KEY como variable de entorno permanente

PowerShell (Windows) — recomendado:

[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "tu-api-key-aqui", "User")

Cierra y abre una nueva terminal para que aplique.

Linux / macOS — añadir a tu shell rc:

echo 'export GEMINI_API_KEY="tu-api-key-aqui"' >> ~/.bashrc   # o ~/.zshrc
source ~/.bashrc

Verificar:

# Linux/macOS
echo $GEMINI_API_KEY

# PowerShell
echo $env:GEMINI_API_KEY

5. Verificar la instalación

Reinicia Claude Code y escribe:

/doctor

Deberías ver transcribir en la lista de skills. O en una sesión nueva, tipea / y verás la skill en el autocomplete.

Test rápido

Graba un voice note y dile a Claude:

"Transcribe este audio: ./mi-nota.ogg"


Uso

Desde Claude Code (lo común)

Simplemente pasa los paths en lenguaje natural:

"Transcribe esto: C:\audios\reunion.mp3"

"Pásame a texto estos voice notes: ~/Downloads/note1.ogg ~/Downloads/note2.ogg"

"Qué dice este audio: ./debug-call.m4a"

Claude detecta los archivos, invoca el script, y te reporta los MDs generados.

Desde la terminal directamente

# Un archivo
python ~/.claude/skills/transcribir/transcribe.py ./audio.ogg

# Varios archivos en paralelo (default 3 simultáneos)
python ~/.claude/skills/transcribir/transcribe.py ./a.ogg ./b.mp3 ./c.m4a

# Toda una carpeta
python ~/.claude/skills/transcribir/transcribe.py ./audios/

# Con MD combinado adicional
python ~/.claude/skills/transcribir/transcribe.py --combined ./resumen.md ./audios/

# Máxima calidad (más caro, más lento)
python ~/.claude/skills/transcribir/transcribe.py --pro ./importante.ogg

# Modelo custom
python ~/.claude/skills/transcribir/transcribe.py --model gemini-3.1-pro-preview ./call.mp3

# Guardar también JSON crudo (útil para reprocesar)
python ~/.claude/skills/transcribir/transcribe.py --json ./audio.ogg

Flags completos

Flag Default Descripción
--pro off Usa gemini-pro-latest (alias auto-upgrade) en vez del Flash default
--model ID gemini-3.5-flash Override del modelo
--json off Guarda JSON crudo además del MD
--out DIR next to audio Carpeta destino
--combined FILE.md off Genera MD unificado adicional
--workers N 3 Concurrencia (max recomendado: 5)

Cómo funciona

            ┌──────────────────┐
audio.ogg ──┤  transcribe.py   ├── transcripción.md
            └────────┬─────────┘
                     │
                     ▼
              ┌─────────────┐
              │ Gemini API  │
              │ 3.5 Flash   │
              └─────────────┘
  1. Lee el audio desde disco. Si pesa <18 MB, lo envía inline. Si pesa más, lo sube por la Files API.
  2. Llama a Gemini con un prompt que fuerza:
    • Output JSON estructurado (response_mime_type=application/json).
    • Fidelidad literal (no interpretar palabras por contexto).
    • Segmentación granular (4-15s por segmento).
    • Diarización por turno.
    • max_output_tokens=32768 y thinking_budget=0 (evita truncations).
  3. Recibe JSON validado y renderiza un Markdown ordenado.
  4. Procesa en paralelo si pasas varios audios (cada thread tiene su propio genai.Client).

Por qué Gemini 3.5 Flash y no otro modelo

Tested empíricamente en mayo 2026 contra gemini-2.5-pro, gemini-2.5-flash, gemini-3-flash-preview. Resultados:

Modelo Calidad transcripción Diarización Tiempo (audio 1m) Costo relativo
gemini-2.5-flash Buena OK ~6s 1x
gemini-3-flash-preview Buena OK ~7s 1x (preview)
gemini-3.5-flash Muy buena Excelente ~6s 1x
gemini-2.5-pro Excelente Excelente ~15s ~10x
gemini-3.1-pro-preview Excelente+ Excelente ~25s ~10x (preview)

3.5 Flash es el sweet spot: calidad casi a la altura de Pro con costo y latencia de Flash. Para audios críticos (acentos atípicos, mucho ruido, muchos hablantes), usa --pro.

Fidelidad literal: por qué importa

Sin instrucciones explícitas, los LLMs "limpian" las transcripciones por contexto. Ejemplo real durante el desarrollo:

Audio dice: "una sencilla sub... ah, tiene una función..." (hablante falso comienzo + autocorrección)

Sin instrucción: "Una sencilla Supabase tiene una función..." (alucinación contextual)

Con instrucción de fidelidad: "Una sencilla sub... ah, tiene una función..." (correcto)

El prompt fuerza al modelo a conservar:

  • Falsos comienzos del hablante (con ... marcando el corte).
  • Tartamudeos y repeticiones (el el la).
  • Muletillas (eh, o sea, tipo).
  • Regionalismos sin normalizar (voseo argentino, "chamo" venezolano, "wey" mexicano, etc.).
  • Marcas/tecnologías mal pronunciadas — se transcriben como suenan, no se "corrigen" al nombre oficial.

Esto es intencional: si vas a darle la transcripción a otra IA downstream, esa IA necesita el contenido real, no una interpretación de Gemini.


Configurar

Cambiar el modelo default

Edita ~/.claude/skills/transcribir/transcribe.py:

DEFAULT_MODEL = "gemini-3.5-flash"  # cámbialo a tu preferencia
PRO_MODEL_ALIAS = "gemini-pro-latest"

Personalizar el prompt

El prompt vive en la constante PROMPT dentro del script. Edita las reglas para tu caso:

  • Quitar fidelidad literal si prefieres transcripciones "limpias".
  • Agregar reglas específicas de tu dominio (ej. medicina: "expandir abreviaturas médicas").
  • Cambiar el idioma del JSON output (todo está en español por default).

Ver modelos disponibles

from google import genai
client = genai.Client()  # lee GEMINI_API_KEY automáticamente
for m in client.models.list():
    if "gemini" in m.name:
        print(m.name)

Troubleshooting

ERROR: GEMINI_API_KEY (or GOOGLE_API_KEY) is not set

La env var no está disponible en la terminal actual. Causas:

  • La seteaste pero no abriste una terminal nueva. Cierra y vuelve a abrir.
  • La seteaste con scope Process en vez de User. Usa [Environment]::SetEnvironmentVariable(..., "User") en PowerShell.
  • En Linux/macOS, no agregaste el export a tu ~/.bashrc o ~/.zshrc.

Gemini returned invalid JSON

Causa típica: el modelo truncó la respuesta. El script ya setea max_output_tokens=32768 que es muy holgado, pero si tu audio dura >2h puede ser insuficiente. Workarounds:

  • Edita el script y sube max_output_tokens a 65536.
  • Procesa el audio en chunks de 30 min con una herramienta como ffmpeg.

Transcripciones truncadas mid-stream cuando paralelizo

Conocido: genai.Client no es thread-safe. El script ya crea un client por thread para evitarlo. Si modificas el código y compartes un client global, vas a ver este problema. Mantén un client por thread.

Calidad mala / palabras erradas

  • Pruébalo con --pro (modelo más capaz).
  • Verifica que el audio tenga calidad razonable (>16 kbps mono mínimo).
  • Si el hablante usa muchos regionalismos atípicos, considera añadir vocabulario específico al prompt.

"Unrecognized file extension"

El script soporta formatos comunes (ver tabla arriba). Si tienes uno raro:

  • Conviértelo con ffmpeg: ffmpeg -i input.amr output.ogg
  • O añade el MIME type a MIME_BY_EXT en el script.

FAQ

¿Cuánto cuesta una transcripción? Con Gemini 3.5 Flash, ~$0.0001 USD por minuto de audio. Un audio de 1 hora cuesta ~$0.006. Para comparación, ElevenLabs Scribe cobra $0.40 por hora (~70x más caro).

¿Funciona offline? No. Requiere conexión para hablar con la API de Gemini. Si necesitas offline, usa Whisper local.

¿Funciona con audios de varias horas? Sí, pero puede acercarse al límite de max_output_tokens. Para audios >2h, considera chunking previo con ffmpeg.

¿Funciona con videos? Sí. Soporta .mp4, .mov, .mpeg, .webm. Gemini extrae el audio del track automáticamente.

¿Identifica al hablante por nombre? No directamente. Usa etiquetas genéricas Hablante 1, Hablante 2. Si quieres mapear a nombres reales, dile a Claude en una segunda pasada: "En la transcripción, Hablante 1 es Juan y Hablante 2 es María".

¿Puedo usar otro modelo de Google (Vertex AI)? El SDK google-genai soporta tanto la AI Studio API como Vertex AI. Para Vertex, modifica el client init en el script: genai.Client(vertexai=True, project="my-proj", location="us-central1").

¿Por qué los prompts están en español? El usuario original es hispanohablante y los audios son en español latino. El modelo entiende y procesa instrucciones en español sin problema — y mantener consistencia de idioma del prompt con idioma de output reduce errores. Si quieres traducir, edita la constante PROMPT en el script.


Créditos

Creado por Josue Bustos en mayo 2026, motivado por el cambio de ElevenLabs Scribe a modelo pago. Originalmente parte del stack interno de Piremos, liberado como skill pública.

Powered by:


Contributing

Issues y PRs bienvenidos. Si encuentras un bug, abre un issue con:

  • Tu OS + versión de Python + versión de google-genai.
  • El comando exacto que corriste.
  • El output completo del error.
  • Idealmente, un audio de muestra que reproduzca el problema (si no es sensible).

License

MIT — usa, modifica, redistribuye. Sin warranty.


Changelog

Ver CHANGELOG.md.

About

Skill de Claude Code que transcribe audios y videos a Markdown estructurado con timestamps y diarización, usando Google Gemini. Reemplazo gratuito de ElevenLabs Scribe / Whisper para quien ya paga Gemini.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors