From e2cf81757a25d43f77cf70054df796ec5d249fde Mon Sep 17 00:00:00 2001 From: Ricardo Gonzalez Date: Tue, 26 May 2026 15:02:48 -0500 Subject: [PATCH] mover inspiracion Handy a RUMBO + flujograma de bloques funcionales --- docs/integracion_handy.md | 379 -------------------------------------- 1 file changed, 379 deletions(-) delete mode 100644 docs/integracion_handy.md diff --git a/docs/integracion_handy.md b/docs/integracion_handy.md deleted file mode 100644 index 3157959..0000000 --- a/docs/integracion_handy.md +++ /dev/null @@ -1,379 +0,0 @@ -# Alpha + Handy — Integración de Transcripción Offline - -> **Inspiración**: Handy (github.com/cjpais/Handy) — 22.4k ⭐, Tauri v2, MIT. -> Alpha toma de Handy su arquitectura de transcripción local con modelos Whisper/Parakeet. - -**Versión**: 1.0 | **Fecha**: 2026-05-26 | **Autor**: Ricardo Gonzalez (Teloprax) - ---- - -## 1. ¿Qué es Handy? - -Handy es una app Tauri v2 que captura audio del micrófono, lo transcribe con modelos locales (Whisper o Parakeet) y pega el texto donde esté el cursor. Todo offline. Es la referencia perfecta para integrar transcripción en RUMBO/Alpha. - -| Aspecto | Handy | Alpha (a integrar) | -|---------|-------|---------------------| -| Shell | Tauri v2 | Tauri v2 ✅ | -| Frontend | React + TS + Tailwind | Vue 3 + TS + Tailwind 🔄 | -| Transcripción | transcribe-rs (Whisper + Parakeet) | transcribe-rs | -| Captura audio | cpal (micrófono) | cpal (micrófono + archivos) | -| VAD (silencio) | vad-rs (Silero) | vad-rs | -| Atajos globales | rdev + tauri-plugin-global-shortcut | rdev + tauri-plugin-global-shortcut | -| Permisos macOS | tauri-plugin-macos-permissions | Ídem | -| Permisos Windows | Win32 APIs (Windows crate) | Ídem | - ---- - -## 2. Arquitectura de transcripción (basada en Handy) - -``` -┌──────────────────────────────────────────────────┐ -│ Alpha (Tauri) │ -│ │ -│ ┌─────────────┐ ┌─────────────────────────┐ │ -│ │ Vue 3 UI │ │ Rust Backend │ │ -│ │ (activar │◄──►│ │ │ -│ │ mic, │ │ ┌───────────────────┐ │ │ -│ │ modelos, │ │ │ Audio Capture │ │ │ -│ │ transc.) │ │ │ (cpal) │ │ │ -│ └─────────────┘ │ │ → micrófono │ │ │ -│ │ │ → archivo .wav │ │ │ -│ │ │ → archivo .mp3 │ │ │ -│ │ │ → video (ffmpeg │ │ │ -│ │ │ extrae audio) │ │ │ -│ │ └───────┬───────────┘ │ │ -│ │ │ audio raw │ │ -│ │ ┌───────▼───────────┐ │ │ -│ │ │ VAD (vad-rs) │ │ │ -│ │ │ → silencio OUT │ │ │ -│ │ │ → voz → buffer │ │ │ -│ │ └───────┬───────────┘ │ │ -│ │ │ segmentos │ │ -│ │ ┌───────▼───────────┐ │ │ -│ │ │ transcribe-rs │ │ │ -│ │ │ → Parakeet V3 │ │ │ -│ │ │ → Whisper Small │ │ │ -│ │ │ → Whisper Turbo │ │ │ -│ │ └───────┬───────────┘ │ │ -│ │ │ texto │ │ -│ │ ┌───────▼───────────┐ │ │ -│ │ │ Post-procesado │ │ │ -│ │ │ → pegar en app │ │ │ -│ │ │ → guardar en DB │ │ │ -│ │ │ → pipeline IA │ │ │ -│ │ └───────────────────┘ │ │ -│ └─────────────────────────┘ │ -└──────────────────────────────────────────────────┘ -``` - ---- - -## 3. Dependencias Rust necesarias - -Inspiradas en el `Cargo.toml` de Handy (v0.8.3): - -```toml -[dependencies] -# Transcripción (core) -transcribe-rs = { version = "0.3", features = ["whisper-cpp", "onnx"] } - -# Audio -cpal = "0.16" # Captura de micrófono -hound = "3.5" # Lectura/escritura de archivos .wav - -# VAD (Voice Activity Detection) -vad-rs = { git = "https://github.com/cjpais/vad-rs", default-features = false } - -# Atajos globales -rdev = { git = "https://github.com/rustdesk-org/rdev" } -tauri-plugin-global-shortcut = "2.3" - -# Permisos -tauri-plugin-macos-permissions = "2.3" - -# Resampling (si se necesita cambiar sample rate) -rubato = "0.16" - -# Audio playback (feedback sonoro) -rodio = "0.16" - -# Utilidades -anyhow = "1.0" -tokio = { version = "1", features = ["full"] } -serde = { version = "1", features = ["derive"] } -serde_json = "1" - -# ─── Plataforma-específicas ─── - -[target.'cfg(target_os = "macos")'.dependencies] -transcribe-rs = { version = "0.3", features = ["whisper-metal"] } - -[target.'cfg(target_os = "windows")'.dependencies] -transcribe-rs = { version = "0.3", features = ["whisper-vulkan", "ort-directml"] } - -[target.'cfg(target_os = "linux")'.dependencies] -transcribe-rs = { version = "0.3", features = ["whisper-vulkan"] } -``` - ---- - -## 4. Modelos de transcripción - -### 4.1 Parakeet V3 (RECOMENDADO) - -| Característica | Detalle | -|---------------|---------| -| Tamaño | ~478 MB (comprimido) | -| Velocidad | ~5x tiempo real en CPU (i5) | -| GPU | No requiere — CPU-optimizado | -| Idioma | Detección automática (sin selección manual) | -| Precisión | Excelente en español e inglés | -| Descarga | `https://blob.handy.computer/parakeet-v3-int8.tar.gz` | -| Backend | ONNX Runtime (vía transcribe-rs feature `onnx`) | - -**Por qué Parakeet V3**: No requiere GPU, funciona en cualquier CPU moderna (Skylake+), velocidad adecuada para transcripción interactiva, y detección automática de idioma (esencial para equipos bilingües español/inglés). - -### 4.2 Whisper (alternativa) - -| Modelo | Tamaño | Velocidad | GPU | -|--------|--------|-----------|-----| -| Small | 487 MB | Rápido | Opcional | -| Medium | 492 MB | Medio | Recomendada | -| Turbo | 1.6 GB | Rápido | Recomendada | -| Large | 1.1 GB | Lento | Necesaria | - -Whisper es más preciso pero más pesado y requiere GPU para velocidad aceptable. Parakeet V3 es mejor opción para Alpha por su eficiencia CPU. - ---- - -## 5. ¿Parakeet V3 para video/audio pregrabado? - -**Sí**, pero con un paso intermedio: extraer el audio del video. - -### Flujo para video - -``` -video.mp4 → ffmpeg (extraer pista de audio) → audio.wav → transcribe-rs → texto -``` - -### Flujo para audio pregrabado - -``` -grabacion.mp3/.ogg/.flac/.m4a → decodificar a PCM/WAV → transcribe-rs → texto -``` - -### Implementación en Rust - -```rust -// Opción A: Usar ffmpeg CLI (sidecar) -use std::process::Command; -Command::new("ffmpeg") - .args(["-i", "video.mp4", "-vn", "-ar", "16000", "-ac", "1", "-f", "wav", "audio.wav"]) - .output()?; - -// Opción B: Usar crate ffmpeg-sidecar (más portátil) -// Opción C: Usar crate symphonia para decodificar audio sin ffmpeg -``` - -### Formatos soportados - -| Fuente | Método | Librería Rust | -|--------|--------|---------------| -| Micrófono (vivo) | cpal → buffer → transcribe-rs | cpal | -| .wav | hound → samples → transcribe-rs | hound | -| .mp3, .ogg, .flac, .m4a | symphonia → decode → transcribe-rs | symphonia | -| Video (.mp4, .mov, .mkv) | ffmpeg → extract audio → transcribe-rs | ffmpeg-sidecar | - ---- - -## 6. Permisos del sistema - -### 6.1 macOS - -| Permiso | Propósito | Cómo solicitarlo | -|---------|-----------|-----------------| -| **Microphone** | Capturar audio del micrófono | Info.plist: `NSMicrophoneUsageDescription` | -| **Accessibility** | Pegar texto en cualquier app | System Preferences → Privacy → Accessibility | -| **Screen Recording** | (futuro) Capturar audio del sistema | Info.plist: `NSScreenCaptureUsageDescription` | - -**Código Info.plist**: -```xml -NSMicrophoneUsageDescription -Alpha necesita acceso al micrófono para transcribir tus reuniones. -``` - -**Detección de permiso (Rust)**: -```rust -use tauri_plugin_macos_permissions; - -// Verificar si el permiso está concedido -let authorized = tauri_plugin_macos_permissions::check_accessibility(); - -// Solicitar permiso -tauri_plugin_macos_permissions::request_accessibility(); -``` - -### 6.2 Windows - -| Permiso | Propósito | Cómo solicitarlo | -|---------|-----------|-----------------| -| **Microphone** | Capturar audio | Windows Settings → Privacy → Microphone | -| **Global shortcuts** | Atajos de teclado | Automático con rdev | - -Windows solicita el permiso automáticamente la primera vez que se usa el micrófono. - -### 6.3 Linux - -| Requisito | Propósito | -|-----------|-----------| -| PulseAudio / ALSA | Captura de audio | -| Grupo `input` | Atajos globales (algunos WMs) | - ---- - -## 7. Flujo de transcripción paso a paso - -### 7.1 Micrófono (tiempo real) - -```rust -use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; -use transcribe_rs::Transcriber; - -// 1. Obtener dispositivo de audio por defecto -let host = cpal::default_host(); -let device = host.default_input_device().unwrap(); -let config = device.default_input_config().unwrap(); - -// 2. Configurar stream de audio -let (tx, rx) = std::sync::mpsc::channel(); -let stream = device.build_input_stream(&config, move |data, _| { - tx.send(data.to_vec()).unwrap(); -}, |err| eprintln!("{}", err), None).unwrap(); -stream.play().unwrap(); - -// 3. Buffer de audio + VAD -let mut buffer: Vec = Vec::new(); -let mut vad = vad_rs::Vad::new(config.sample_rate().0); - -// 4. Acumular voz, ignorar silencio -while let Ok(samples) = rx.recv_timeout(Duration::from_millis(100)) { - for &sample in &samples { - if vad.is_voice(sample) { - buffer.push(sample); - } - } - if buffer.len() > config.sample_rate().0 as usize * 3 { - break; // 3 segundos de voz → transcribir - } -} - -// 5. Transcribir con Parakeet V3 -let transcriber = Transcriber::new("parakeet-tdt-0.6b-v3-int8")?; -let text = transcriber.transcribe(&buffer, config.sample_rate().0)?; -println!("{}", text); -``` - -### 7.2 Archivo de audio/video - -```rust -// 1. Si es video, extraer audio con ffmpeg -// 2. Leer archivo .wav -use hound::WavReader; -let mut reader = WavReader::open("audio.wav")?; -let samples: Vec = reader.samples::() - .map(|s| s.unwrap() as f32 / i16::MAX as f32) - .collect(); - -// 3. Transcribir -let transcriber = Transcriber::new("parakeet-tdt-0.6b-v3-int8")?; -let text = transcriber.transcribe(&samples, reader.spec().sample_rate)?; -``` - ---- - -## 8. Descarga y gestión de modelos - -Inspirado en Handy, los modelos se almacenan en: - -| SO | Ruta | -|----|------| -| macOS | `~/Library/Application Support/com.teloprax.alpha/models/` | -| Windows | `%APPDATA%\com.teloprax.alpha\models\` | -| Linux | `~/.config/com.teloprax.alpha/models/` | - -### Estructura esperada - -``` -models/ -├── parakeet-tdt-0.6b-v3-int8/ ← Parakeet V3 (recomendado) -│ ├── model.onnx -│ ├── config.json -│ └── tokenizer.json -├── ggml-small.bin ← Whisper Small (alternativo) -└── ggml-large-v3-turbo.bin ← Whisper Turbo (alternativo) -``` - -### Descarga programática - -```rust -use reqwest; -use flate2::read::GzDecoder; -use tar::Archive; - -async fn download_model(url: &str, dest: &Path) -> Result<()> { - let response = reqwest::get(url).await?; - let bytes = response.bytes().await?; - - // Extraer si es .tar.gz (Parakeet), copiar si es .bin (Whisper) - if url.ends_with(".tar.gz") { - let gz = GzDecoder::new(&bytes[..]); - let mut archive = Archive::new(gz); - archive.unpack(dest)?; - } else { - std::fs::write(dest.join(url.split('/').last().unwrap()), &bytes)?; - } - Ok(()) -} -``` - ---- - -## 9. Diferencia clave Alpha vs Handy - -Handy es una app de propósito general (transcribir y pegar). Alpha lo integra en el flujo de gestión de proyectos: - -| Capacidad | Handy | Alpha | -|-----------|-------|-------| -| Transcribir micrófono | ✅ | ✅ (para reuniones) | -| Pegar texto en cualquier app | ✅ | ⬜ (no necesario) | -| Transcribir archivos de audio | ⬜ | ✅ (.mp3, .wav, .ogg) | -| Extraer audio de video | ⬜ | ✅ (vía ffmpeg) | -| Pipeline IA post-transcripción | ⬜ | ✅ (→ análisis → HUs → KAPPA) | -| Guardar transcripción en proyecto | ⬜ | ✅ (Turso + contexto de proyecto) | -| Memoria de proyecto | ⬜ | ✅ (contexto_transcripciones.md) | -| Integración con KAPPA | ⬜ | ✅ (crear HUs automáticamente) | - ---- - -## 10. Roadmap de integración - -| Fase | Alcance | Prioridad | -|------|---------|-----------| -| **T1** | Agregar dependencias Rust (transcribe-rs, cpal, vad-rs) | 🔴 Alta | -| **T2** | Captura de micrófono + transcripción Parakeet V3 | 🔴 Alta | -| **T3** | Descarga de modelos desde UI | 🟡 Media | -| **T4** | Transcripción de archivos (.wav, .mp3) | 🟡 Media | -| **T5** | Transcripción de video (extracción audio) | 🟢 Baja | -| **T6** | Pipeline completo: audio → transcripción → IA → HUs | 🔴 Alta | -| **T7** | Permisos macOS/Windows UI | 🟡 Media | - ---- - -## 11. Referencias - -- [Handy GitHub](https://github.com/cjpais/Handy) -- [transcribe-rs crate](https://crates.io/crates/transcribe-rs) -- [cpal crate](https://crates.io/crates/cpal) -- [vad-rs (fork de Handy)](https://github.com/cjpais/vad-rs) -- [Parakeet models (HuggingFace)](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3) -- [Tauri Plugin macOS Permissions](https://github.com/ahkohd/tauri-plugin-macos-permissions)