Paso 4: Benchmark y Integración - whisper.cpp optimizado para AMD A4-9125
Estado Actual ✅
- whisper-amd compilado con OpenCL + OpenBLAS
- Modelos TINY (75MB) y BASE (141MB) descargados
- Configuración optimizada para 2 threads
- Sistema listo para pruebas de rendimiento
Script de Benchmark Completo
#!/bin/bash
# benchmark_whisper_amd_final.sh
echo "⚡ BENCHMARK FINAL WHISPER-AMD EN AMD A4-9125"
echo "============================================="
source "$HOME/.whisper_amd_config" 2>/dev/null || {
echo "❌ Configuración no encontrada"
echo "💡 Ejecuta: source ~/.whisper_amd_config"
exit 1
}
echo "🔧 Configuración actual:"
echo "📁 Modelos: $WHISPER_MODELS_DIR"
echo "🧵 Threads: $WHISPER_THREADS"
echo "🧠 Modelo por defecto: $WHISPER_DEFAULT_MODEL"
# Crear audio de prueba realista
echo -e "\n🎙️ Creando audio de prueba..."
TEST_AUDIO="/tmp/whisper_benchmark_test.wav"
# Crear audio sintético que simule habla (más realista que un tono)
if command -v ffmpeg >/dev/null 2>&1; then
# Generar audio que simula habla humana con variaciones de frecuencia
ffmpeg -f lavfi -i "sine=frequency=440:duration=1,sine=frequency=880:duration=1,sine=frequency=220:duration=1" \
-filter_complex "aformat=channel_layouts=mono:sample_rates=16000" \
-t 15 "$TEST_AUDIO" -y 2>/dev/null
echo "✅ Audio de prueba creado: 15 segundos"
elif command -v sox >/dev/null 2>&1; then
# Fallback con sox
sox -n -r 16000 -c 1 "$TEST_AUDIO" synth 15 sine 440 sine 880 sine 220
echo "✅ Audio de prueba creado con sox: 15 segundos"
else
echo "❌ Necesitas ffmpeg o sox para crear audio de prueba"
echo "💡 Instala: sudo apt install ffmpeg"
exit 1
fi
# Función de benchmark mejorada
run_detailed_benchmark() {
local model="$1"
local model_file="$WHISPER_MODELS_DIR/ggml-${model}.bin"
if [ ! -f "$model_file" ]; then
echo "❌ Modelo $model no encontrado: $model_file"
return 1
fi
echo -e "\n🧠 BENCHMARK MODELO: $model"
echo "=============================="
echo "📊 Archivo: $(basename "$model_file")"
# Información del modelo
model_size=$(stat -c%s "$model_file" 2>/dev/null | awk '{print int($1/1024/1024)"MB"}')
echo "💾 Tamaño del modelo: $model_size"
# Limpiar archivos previos
rm -f /tmp/whisper_benchmark_test.* 2>/dev/null
echo "🚀 Iniciando transcripción..."
echo "⏱️ Midiendo rendimiento..."
# Benchmark detallado con información del sistema
start_time=$(date +%s.%N)
start_mem=$(free -m | awk 'NR==2{printf "%.0f", $3}')
# Ejecutar transcripción con parámetros optimizados para A4-9125
if timeout 180s whisper-amd \
-m "$model_file" \
-t 2 \
-p 1 \
-l auto \
--output-txt \
--output-srt \
--output-dir "/tmp" \
--print-progress \
"$TEST_AUDIO" > "/tmp/whisper_output_$model.log" 2>&1; then
end_time=$(date +%s.%N)
end_mem=$(free -m | awk 'NR==2{printf "%.0f", $3}')
# Calcular métricas
duration=$(echo "$end_time - $start_time" | bc 2>/dev/null || echo "N/A")
mem_used=$((end_mem - start_mem))
audio_duration=15 # segundos de audio
echo "✅ Transcripción completada"
echo "⏱️ Tiempo total: ${duration}s"
echo "🧠 Memoria usada: ${mem_used}MB"
# Calcular factor de tiempo real
if [ "$duration" != "N/A" ]; then
factor=$(echo "scale=2; $duration / $audio_duration" | bc 2>/dev/null || echo "N/A")
echo "🚀 Factor tiempo real: ${factor}x"
# Evaluación de rendimiento
if (( $(echo "$factor < 0.5" | bc -l 2>/dev/null || echo 0) )); then
echo "🏆 RENDIMIENTO: EXCELENTE (Más de 2x tiempo real)"
elif (( $(echo "$factor < 1.0" | bc -l 2>/dev/null || echo 0) )); then
echo "🎯 RENDIMIENTO: MUY BUENO (Más rápido que tiempo real)"
elif (( $(echo "$factor < 2.0" | bc -l 2>/dev/null || echo 0) )); then
echo "✅ RENDIMIENTO: BUENO (Hasta 2x tiempo real)"
elif (( $(echo "$factor < 4.0" | bc -l 2>/dev/null || echo 0) )); then
echo "👍 RENDIMIENTO: ACEPTABLE (Hasta 4x tiempo real)"
else
echo "⚠️ RENDIMIENTO: LENTO (Más de 4x tiempo real)"
fi
# Calcular velocidad de procesamiento
speed=$(echo "scale=2; $audio_duration / $duration" | bc 2>/dev/null || echo "N/A")
echo "📈 Velocidad de procesamiento: ${speed}x"
fi
# Mostrar resultado de transcripción
result_file="/tmp/whisper_benchmark_test.txt"
if [ -f "$result_file" ]; then
result_text=$(cat "$result_file" | head -c 200)
echo "📝 Resultado (primeros 200 chars): $result_text..."
# Contar palabras transcritas
word_count=$(cat "$result_file" | wc -w)
echo "📊 Palabras transcritas: $word_count"
fi
# Mostrar log si hay errores
if [ -f "/tmp/whisper_output_$model.log" ]; then
if grep -q "error\|Error\|ERROR" "/tmp/whisper_output_$model.log"; then
echo "⚠️ Errores encontrados en el log:"
grep -i error "/tmp/whisper_output_$model.log" | head -3
fi
fi
return 0
else
echo "❌ Transcripción falló o timeout (180s)"
if [ -f "/tmp/whisper_output_$model.log" ]; then
echo "📋 Últimas líneas del log:"
tail -5 "/tmp/whisper_output_$model.log"
fi
return 1
fi
}
# Información del sistema antes del benchmark
echo -e "\n🖥️ INFORMACIÓN DEL SISTEMA:"
echo "=========================="
echo "🔧 CPU: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
echo "🧠 RAM total: $(free -h | awk 'NR==2{print $2}')"
echo "🧠 RAM disponible: $(free -h | awk 'NR==2{print $7}')"
echo "💿 Espacio /tmp: $(df -h /tmp | awk 'NR==2{print $4}')"
echo "🌡️ Temperatura CPU: $(sensors 2>/dev/null | grep -i 'core 0' | awk '{print $3}' || echo 'N/A')"
# Ejecutar benchmarks
echo -e "\n🏁 EJECUTANDO BENCHMARKS:"
echo "========================="
# Benchmark modelo TINY
run_detailed_benchmark "tiny"
# Pequeña pausa entre benchmarks
echo -e "\n⏸️ Pausa de 5 segundos entre benchmarks..."
sleep 5
# Benchmark modelo BASE
run_detailed_benchmark "base"
# Resumen final
echo -e "\n📊 RESUMEN FINAL - AMD A4-9125:"
echo "==============================="
echo "🎯 Mejor para velocidad: MODELO TINY"
echo "⚖️ Mejor equilibrio: MODELO BASE"
echo "🔧 Configuración óptima: 2 threads, 1 processor"
echo "🚀 OpenCL: Habilitado (Radeon R3)"
echo "⚡ OpenBLAS: Habilitado (matemáticas optimizadas)"
echo -e "\n💡 RECOMENDACIONES DE USO:"
echo "========================="
echo "📹 Transcripción en tiempo real: whisper-tiny"
echo "🎓 Clases/reuniones: whisper-base"
echo "📝 Documentos importantes: whisper-base"
echo "🎙️ Podcasts/entrevistas: whisper-base"
echo -e "\n🧹 Limpiando archivos temporales..."
rm -f /tmp/whisper_benchmark_test.* /tmp/whisper_output_*.log 2>/dev/null
echo -e "\n🎉 ¡BENCHMARK COMPLETADO!"
echo "whisper-amd optimizado para AMD A4-9125 ✅"
Actualización del ProcessingAgent para usar whisper-amd nativo
# agents/processing_agent_whisper_amd.py
import os
import subprocess
import sys
from pathlib import Path
import datetime
# Add the project root to Python path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from mcp.agent_framework import AgentFramework
class ProcessingAgentWhisperAMD(AgentFramework):
"""
ProcessingAgent optimizado para AMD A4-9125 usando whisper-amd nativo.
Reemplaza completamente el uso de openai-whisper por whisper.cpp compilado.
"""
def __init__(self):
super().__init__("ProcessingAgentWhisperAMD")
self.config = self._load_config()
self.audio_settings = self.config.get('audio_settings', {})
# Paths
self.transcripts_dir = Path('recordings/transcripts')
self.transcripts_dir.mkdir(parents=True, exist_ok=True)
# Configuración whisper-amd
self.whisper_amd_binary = "/usr/local/bin/whisper-amd"
self.whisper_models_dir = Path.home() / "whisper_models"
# Modelos disponibles (en orden de preferencia para A4-9125)
self.available_models = {
"tiny": "ggml-tiny.bin", # Más rápido, buena precisión
"base": "ggml-base.bin", # Equilibrado (recomendado)
"small": "ggml-small.bin" # Mejor precisión, más lento
}
# Verificar instalación
self._verify_whisper_amd_installation()
print(f"[{self.agent_name}] Initialized with whisper-amd native support.")
print(f"[{self.agent_name}] Models directory: {self.whisper_models_dir}")
print(f"[{self.agent_name}] Available models: {list(self.available_models.keys())}")
def _verify_whisper_amd_installation(self):
"""Verifica que whisper-amd esté instalado y funcional."""
if not Path(self.whisper_amd_binary).exists():
print(f"[{self.agent_name}] ERROR: whisper-amd not found at {self.whisper_amd_binary}")
print(f"[{self.agent_name}] Please install whisper-amd first.")
self.whisper_amd_available = False
return
try:
# Probar que whisper-amd responde
result = subprocess.run([self.whisper_amd_binary, "--help"],
capture_output=True, text=True, timeout=10)
if result.returncode == 0:
print(f"[{self.agent_name}] whisper-amd verified and functional.")
self.whisper_amd_available = True
else:
print(f"[{self.agent_name}] WARNING: whisper-amd exists but not responding correctly.")
self.whisper_amd_available = False
except Exception as e:
print(f"[{self.agent_name}] ERROR testing whisper-amd: {e}")
self.whisper_amd_available = False
def _get_model_path(self, model_name: str) -> Path:
"""Obtiene la ruta completa del modelo especificado."""
if model_name not in self.available_models:
print(f"[{self.agent_name}] WARNING: Unknown model '{model_name}', using 'base'")
model_name = "base"
model_file = self.available_models[model_name]
model_path = self.whisper_models_dir / model_file
if not model_path.exists():
print(f"[{self.agent_name}] ERROR: Model file not found: {model_path}")
print(f"[{self.agent_name}] Please download models first.")
return None
return model_path
def transcribe_audio_amd_optimized(self, audio_filepath: Path,
output_filename: str = None,
language: str = None,
model: str = "base") -> dict:
"""
Transcripción optimizada usando whisper-amd nativo para AMD A4-9125.
Args:
audio_filepath (Path): Ruta del archivo de audio
output_filename (str): Nombre base para archivos de salida
language (str): Código de idioma ('es', 'en', etc.) o None para auto-detect
model (str): Modelo a usar ('tiny', 'base', 'small')
Returns:
dict: Información de la transcripción o None si falla
"""
if not self.whisper_amd_available:
print(f"[{self.agent_name}] whisper-amd not available, cannot transcribe.")
return None
if not audio_filepath.exists():
print(f"[{self.agent_name}] Audio file not found: {audio_filepath}")
return None
# Obtener ruta del modelo
model_path = self._get_model_path(model)
if not model_path:
return None
print(f"[{self.agent_name}] Starting AMD-optimized transcription...")
print(f"[{self.agent_name}] Audio: {audio_filepath.name}")
print(f"[{self.agent_name}] Model: {model} ({model_path.name})")
print(f"[{self.agent_name}] Language: {language or 'auto-detect'}")
# Preparar comando whisper-amd optimizado para A4-9125
whisper_cmd = [
self.whisper_amd_binary,
"-m", str(model_path),
"-t", "2", # 2 threads óptimo para A4-9125
"-p", "1", # 1 processor
"--output-txt", # Generar archivo .txt
"--output-srt", # Generar subtítulos .srt
"--output-vtt", # Generar subtítulos .vtt
"--output-dir", str(self.transcripts_dir),
]
# Agregar idioma si se especifica
if language:
whisper_cmd.extend(["-l", language])
# Agregar archivo de audio
whisper_cmd.append(str(audio_filepath))
try:
print(f"[{self.agent_name}] Executing: {' '.join(whisper_cmd[:8])}... [truncated]")
# Ejecutar transcripción
start_time = datetime.datetime.now()
result = subprocess.run(
whisper_cmd,
capture_output=True,
text=True,
timeout=600 # 10 minutos máximo
)
end_time = datetime.datetime.now()
duration = (end_time - start_time).total_seconds()
if result.returncode == 0:
# Buscar archivo de texto generado
base_name = audio_filepath.stem
txt_file = self.transcripts_dir / f"{base_name}.txt"
srt_file = self.transcripts_dir / f"{base_name}.srt"
transcript_text = ""
if txt_file.exists():
with open(txt_file, 'r', encoding='utf-8') as f:
transcript_text = f.read().strip()
if transcript_text:
print(f"[{self.agent_name}] AMD transcription successful!")
print(f"[{self.agent_name}] Duration: {duration:.2f}s")
print(f"[{self.agent_name}] Output files: {txt_file.name}")
if srt_file.exists():
print(f"[{self.agent_name}] Subtitles: {srt_file.name}")
# Calcular estadísticas
word_count = len(transcript_text.split())
char_count = len(transcript_text)
return {
"text": transcript_text,
"path": str(txt_file),
"srt_path": str(srt_file) if srt_file.exists() else None,
"language": language or "auto-detected",
"model": model,
"method": "whisper-amd-native",
"duration_seconds": duration,
"word_count": word_count,
"char_count": char_count,
"processing_speed": f"{duration:.2f}s"
}
else:
print(f"[{self.agent_name}] Transcription completed but no text found.")
else:
print(f"[{self.agent_name}] whisper-amd failed with return code: {result.returncode}")
print(f"[{self.agent_name}] Error output: {result.stderr}")
except subprocess.TimeoutExpired:
print(f"[{self.agent_name}] Transcription timeout (10 minutes exceeded)")
except Exception as e:
print(f"[{self.agent_name}] Error during AMD transcription: {e}")
return None
def run(self):
"""Ejecución de prueba del ProcessingAgent optimizado."""
print(f"[{self.agent_name}] Running AMD-optimized ProcessingAgent test...")
# Buscar archivo de audio para probar
raw_recordings_path = Path('recordings/raw')
if not raw_recordings_path.exists():
print(f"[{self.agent_name}] No recordings directory found. Creating test audio...")
# Aquí podrías crear un audio de prueba o usar el del benchmark
test_audio = Path("/tmp/whisper_benchmark_test.wav")
if test_audio.exists():
print(f"[{self.agent_name}] Using benchmark test audio for demonstration.")
self._test_transcription(test_audio)
else:
print(f"[{self.agent_name}] No test audio available.")
return
# Buscar archivos de audio existentes
audio_files = list(raw_recordings_path.glob('*.wav'))
if not audio_files:
print(f"[{self.agent_name}] No audio files found in {raw_recordings_path}")
return
# Usar el archivo más reciente
latest_audio = max(audio_files, key=lambda x: x.stat().st_mtime)
print(f"[{self.agent_name}] Testing with latest audio: {latest_audio.name}")
self._test_transcription(latest_audio)
def _test_transcription(self, audio_file: Path):
"""Prueba de transcripción con diferentes modelos."""
print(f"[{self.agent_name}] Testing transcription with different models...")
# Probar modelo tiny (más rápido)
print(f"\n[{self.agent_name}] Testing TINY model...")
result_tiny = self.transcribe_audio_amd_optimized(
audio_file,
language="es",
model="tiny"
)
if result_tiny:
print(f"[{self.agent_name}] TINY result: {result_tiny['text'][:100]}...")
print(f"[{self.agent_name}] TINY speed: {result_tiny['processing_speed']}")
# Probar modelo base (equilibrado)
print(f"\n[{self.agent_name}] Testing BASE model...")
result_base = self.transcribe_audio_amd_optimized(
audio_file,
language="es",
model="base"
)
if result_base:
print(f"[{self.agent_name}] BASE result: {result_base['text'][:100]}...")
print(f"[{self.agent_name}] BASE speed: {result_base['processing_speed']}")
print(f"[{self.agent_name}] AMD ProcessingAgent test completed!")
if __name__ == "__main__":
# Test del ProcessingAgent optimizado
processing_agent = ProcessingAgentWhisperAMD()
processing_agent.run()
Script de Prueba Completa de Integración
#!/bin/bash
# test_complete_integration.sh
echo "🚀 PRUEBA COMPLETA DE INTEGRACIÓN WHISPER-AMD"
echo "============================================="
source "$HOME/.whisper_amd_config" 2>/dev/null || {
echo "❌ Configuración no encontrada"
exit 1
}
echo "✅ Configuración cargada"
echo "📁 Modelos en: $WHISPER_MODELS_DIR"
# Crear audio de prueba realista
echo -e "\n🎙️ Creando audio de prueba con texto en español..."
TEST_AUDIO="/tmp/test_integration_spanish.wav"
if command -v espeak >/dev/null 2>&1; then
# Crear audio con texto en español usando espeak
echo "Hola, esta es una prueba de transcripción en español para verificar el funcionamiento de whisper en AMD A4-9125. La ciberseguridad es importante." | \
espeak -v es -s 150 -w "$TEST_AUDIO"
echo "✅ Audio de prueba creado con espeak"
elif command -v ffmpeg >/dev/null 2>&1; then
# Fallback con ffmpeg
ffmpeg -f lavfi -i "sine=frequency=440:duration=10" -ar 16000 -ac 1 "$TEST_AUDIO" -y 2>/dev/null
echo "✅ Audio sintético creado"
else
echo "❌ Necesitas espeak o ffmpeg"
exit 1
fi
# Prueba completa con ambos modelos
echo -e "\n🧪 PRUEBA COMPLETA DE TRANSCRIPCIÓN:"
echo "=================================="
for model in tiny base; do
echo -e "\n🧠 Probando modelo: $model"
echo "----------------------"
output_dir="/tmp/whisper_test_$model"
mkdir -p "$output_dir"
start_time=$(date +%s)
if whisper-amd \
-m "$WHISPER_MODELS_DIR/ggml-$model.bin" \
-t 2 \
-p 1 \
-l es \
--output-txt \
--output-srt \
--output-dir "$output_dir" \
"$TEST_AUDIO"; then
end_time=$(date +%s)
duration=$((end_time - start_time))
echo "✅ Transcripción $model completada en ${duration}s"
# Mostrar resultado
txt_file="$output_dir/$(basename "$TEST_AUDIO" .wav).txt"
if [ -f "$txt_file" ]; then
echo "📝 Resultado:"
cat "$txt_file"
# Contar palabras
word_count=$(cat "$txt_file" | wc -w)
echo "📊 Palabras: $word_count"
fi
# Verificar subtítulos
srt_file="$output_dir/$(basename "$TEST_AUDIO" .wav).srt"
if [ -f "$srt_file" ]; then
echo "📹 Subtítulos SRT generados"
fi
else
echo "❌ Error en transcripción $model"
fi
done
# Limpiar
rm -f "$TEST_AUDIO" 2>/dev/null
rm -rf /tmp/whisper_test_* 2>/dev/null
echo -e "\n🎉 ¡INTEGRACIÓN COMPLETADA!"
echo "whisper-amd listo para usar en producción ✅"
Paso 4: Benchmark y Integración - whisper.cpp optimizado para AMD A4-9125
Estado Actual ✅
Script de Benchmark Completo
Actualización del ProcessingAgent para usar whisper-amd nativo
Script de Prueba Completa de Integración