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.
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.
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 etiquetaHablante 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.
Recibes 3 audios de WhatsApp del equipo (3.5 min en total). Para procesarlos con tu IA:
- Subes uno por uno a ElevenLabs/Whisper online.
- Esperas la transcripción (sin estructura).
- Copias-pegas a un chat.
- Le pides que separe por hablantes y por temas.
- Pierdes 10-15 minutos por cada lote.
Le dices a Claude Code:
"Transcribe estos audios:
C:\audios\nota1.oggC:\audios\nota2.oggC:\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- Python 3.10+ instalado.
- API key de Google Gemini — gratuita en aistudio.google.com/apikey.
- Claude Code instalado.
git clone https://github.com/josuebustosn/gemini-transcribe.git
cd gemini-transcribepip install -r requirements.txtLinux / 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.
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 ~/.bashrcVerificar:
# Linux/macOS
echo $GEMINI_API_KEY
# PowerShell
echo $env:GEMINI_API_KEYReinicia 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.
Graba un voice note y dile a Claude:
"Transcribe este audio:
./mi-nota.ogg"
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.
# 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| 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) |
┌──────────────────┐
audio.ogg ──┤ transcribe.py ├── transcripción.md
└────────┬─────────┘
│
▼
┌─────────────┐
│ Gemini API │
│ 3.5 Flash │
└─────────────┘
- Lee el audio desde disco. Si pesa <18 MB, lo envía inline. Si pesa más, lo sube por la Files API.
- 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=32768ythinking_budget=0(evita truncations).
- Output JSON estructurado (
- Recibe JSON validado y renderiza un Markdown ordenado.
- Procesa en paralelo si pasas varios audios (cada thread tiene su propio
genai.Client).
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.
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.
Edita ~/.claude/skills/transcribir/transcribe.py:
DEFAULT_MODEL = "gemini-3.5-flash" # cámbialo a tu preferencia
PRO_MODEL_ALIAS = "gemini-pro-latest"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).
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)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
Processen vez deUser. Usa[Environment]::SetEnvironmentVariable(..., "User")en PowerShell. - En Linux/macOS, no agregaste el
exporta tu~/.bashrco~/.zshrc.
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_tokensa65536. - Procesa el audio en chunks de 30 min con una herramienta como
ffmpeg.
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.
- 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.
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_EXTen el script.
¿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.
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:
- Google Gemini API — modelos
gemini-3.5-flashygemini-pro-latest. - google-genai Python SDK.
- Claude Code — el orquestador.
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).
MIT — usa, modifica, redistribuye. Sin warranty.
Ver CHANGELOG.md.