Discussions

Ask a Question
Back to All

Problema de falsos positivos en la detección de audio en Streaming Avatar SDK

Hola a todos,

Estoy trabajando con el SDK de Streaming Avatar de HeyGen en un proyecto de avatar interactivo en tiempo real. Hemos implementado un sistema de detección y procesamiento de audio que funciona bastante bien, pero estamos enfrentando un problema específico con los falsos positivos.

Contexto técnico:

  • Estamos usando Vite 6.0.6 con TypeScript 5.6.3
  • Dependencias principales: @heygen/streaming-avatar, livekit-client, openai
  • Sistema operativo: AlmaLinux 8.10
  • No estamos usando React, solo JavaScript/TypeScript vanilla con HTML5 y CSS3

El problema:

Cuando hay ruidos fuertes de fondo (aplausos, golpes, etc.), nuestro sistema interpreta estos sonidos como consultas válidas y envía solicitudes a la API de OpenAI, lo que resulta en respuestas irrelevantes como "Gracias por ver el video en YouTube" u otras frases sin relación con la conversación.

Implementación actual:

Nuestro AudioRecorder utiliza la Web Audio API para analizar el audio en tiempo real:

private detectSpeech() {  
    const bufferLength = this.analyser!.frequencyBinCount;  
    const dataArray = new Uint8Array(bufferLength);
    const checkAudio = () => {
    if (!this.isListening || !this.analyser) return;
    
    this.analyser.getByteFrequencyData(dataArray);
    
    // Calcular el nivel promedio de audio
    let sum = 0;
    for (let i = 0; i < bufferLength; i++) {
        sum += dataArray[i];
    }
    const average = sum / bufferLength;
    
    // Normalizar el nivel de audio para callbacks
    const normalizedLevel = average / 255;
    
    // Enviar el nivel de audio al callback si existe
    if (this.voiceLevelCallback) {
        this.voiceLevelCallback(normalizedLevel);
    }
    
    // Actualizar el indicador visual
    this.updateVoiceIndicator(normalizedLevel);

    // Detectar si hay habla usando el umbral personalizado
    if (average > this.voiceThreshold) { // Usar el umbral personalizado
        if (!this.isSpeaking) {
            this.isSpeaking = true;
            this.statusCallback('Voz detectada');
            if (this.recordingStateCallback) {
                this.recordingStateCallback(true);
            }
            
            // Activar indicador visual
            if (this.voiceIndicator) {
                this.voiceIndicator.classList.add("active", "voice-active");
                this.voiceIndicator.classList.remove("voice-idle");
            }
        }
        
        // Limpiar el temporizador de silencio si existe
        if (this.silenceTimer) {
            clearTimeout(this.silenceTimer);
            this.silenceTimer = null;
        }
    } else if (this.isSpeaking) {
        // Si estaba hablando pero ahora hay silencio, iniciar temporizador
        if (!this.silenceTimer) {
            this.silenceTimer = setTimeout(() => {
                this.isSpeaking = false;
                
                // Detener la grabación actual para procesar el audio
                if (this.mediaRecorder && this.mediaRecorder.state === "recording") {
                    this.mediaRecorder.stop();
                }
                
                this.statusCallback('Procesando habla...');
                
                // Cambiar el indicador visual
                if (this.voiceIndicator) {
                    this.voiceIndicator.classList.remove("voice-active");
                    this.voiceIndicator.classList.add("voice-idle");
                }
            }, this.silenceDuration); // Usar la duración personalizada
        }
    }

    // Continuar verificando el audio
    if (this.isListening) {
        requestAnimationFrame(checkAudio);
    }
};

// Iniciar el bucle de verificación
checkAudio();
}

Actualmente, nuestros parámetros de configuración son:

  • voiceThreshold: 2 (umbral para detectar voz, escala 0-255)
  • silenceDuration: 1500 (ms antes de considerar que terminó el habla)
  • minDecibel: -80 (sensibilidad del analizador en dB)

Lo que hemos intentado:

  1. Ajustar el voiceThreshold a valores más altos (hasta 10), pero esto afecta la detección de voces suaves
  2. Aumentar silenceDuration para evitar cortes en pausas naturales del habla
  3. Experimentar con diferentes valores de minDecibels

Preguntas:

  1. ¿Existe alguna técnica recomendada para distinguir entre voz humana y ruidos ambientales usando la Web Audio API?
  2. ¿Hay algún patrón de frecuencia específico que podríamos analizar para filtrar mejor los ruidos no vocales?
  3. ¿Alguien ha implementado algún algoritmo de detección de voz más sofisticado que pueda compartir?
  4. ¿La API de HeyGen ofrece alguna funcionalidad nativa para manejar este tipo de situaciones que no estemos aprovechando?

Cualquier sugerencia o experiencia similar sería de gran ayuda. Gracias de antemano.