Visão Geral

O ConnectVets Notes processa arquivos de áudio de consultas veterinárias para gerar transcrições e análises estruturadas. A qualidade do áudio impacta diretamente na precisão dos resultados.
Recomendação: Áudios de boa qualidade resultam em transcrições 95%+ precisas e análises mais detalhadas.

Formatos Suportados

Formatos Aceitos

FormatoExtensãoRecomendadoQualidadeTamanho
MP3.mp3SIMBoaMédio
WAV.wavIDEALExcelenteGrande
M4A.m4aSIMBoaMédio
AAC.aacSIMBoaPequeno
OGG.ogg⚠️ LimitadoBoaMédio
WEBM.webm⚠️ LimitadoBoaMédio

Formato Recomendado: WAV

# Especificações ideais para WAV
Formato: WAV (PCM)
Sample Rate: 44.1 kHz ou 48 kHz
Bit Depth: 16-bit ou 24-bit
Canais: Mono ou Estéreo
Duração máxima: 60 minutos
Tamanho máximo: 25 MB

Especificações Técnicas

Qualidade de Áudio

Requisitos Mínimos

  • Sample Rate: 16 kHz+
  • Bit Depth: 16-bit+
  • Duração: 10 segundos - 60 minutos
  • Tamanho: Máximo 100 MB
  • SNR: 15 dB+ (Signal-to-Noise Ratio)

Configuração Ideal

  • Sample Rate: 44.1 kHz ou 48 kHz
  • Bit Depth: 24-bit
  • Duração: 5-45 minutos
  • Tamanho: 20-80 MB
  • SNR: 25 dB+

Limitações de Tamanho

// Validação de arquivo no frontend
function validateAudioFile(file) {
  const maxSize = 25 * 1024 * 1024; // 100 MB
  const minSize = 1 * 1024; // 1 KB
  const supportedFormats = ['mp3', 'wav', 'm4a', 'aac'];
  
  // Verificar tamanho
  if (file.size > maxSize) {
    return { 
      valid: false, 
      error: 'Arquivo muito grande. Máximo: 100 MB' 
    };
  }
  
  if (file.size < minSize) {
    return { 
      valid: false, 
      error: 'Arquivo muito pequeno. Mínimo: 1 KB' 
    };
  }
  
  // Verificar formato
  const extension = file.name.toLowerCase().split('.').pop();
  if (!supportedFormats.includes(extension)) {
    return { 
      valid: false, 
      error: `Formato não suportado. Use: ${supportedFormats.join(', ')}` 
    };
  }
  
  return { valid: true };
}

// Uso da validação
const fileInput = document.getElementById('audio-file');
fileInput.addEventListener('change', (event) => {
  const file = event.target.files[0];
  const validation = validateAudioFile(file);
  
  if (!validation.valid) {
    alert(validation.error);
    return;
  }
  
  // Arquivo válido, prosseguir com upload
  uploadAudio(file);
});

Configuração de Gravação

Configurações do Microfone

Ambiente de Gravação

Configuração de Software

// Configuração para gravação no navegador
async function configureAudioRecording() {
  const constraints = {
    audio: {
      sampleRate: 48000,        // Sample rate alto
      channelCount: 1,          // Mono (suficiente para voz)
      echoCancellation: true,   // Cancelamento de eco
      noiseSuppression: true,   // Supressão de ruído
      autoGainControl: true,    // Controle automático de ganho
      sampleSize: 16            // 16-bit depth
    }
  };
  
  try {
    const stream = await navigator.mediaDevices.getUserMedia(constraints);
    const mediaRecorder = new MediaRecorder(stream, {
      mimeType: 'audio/webm;codecs=opus',
      audioBitsPerSecond: 128000  // 128 kbps
    });
    
    return mediaRecorder;
  } catch (error) {
    console.error('Erro ao configurar gravação:', error);
  }
}

Otimização de Áudio

Pré-processamento

// Normalizar volume do áudio antes de enviar
async function normalizeAudio(audioBlob) {
  const audioContext = new AudioContext();
  const arrayBuffer = await audioBlob.arrayBuffer();
  const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
  
  // Encontrar pico máximo
  const channelData = audioBuffer.getChannelData(0);
  let maxPeak = 0;
  
  for (let i = 0; i < channelData.length; i++) {
    const sample = Math.abs(channelData[i]);
    if (sample > maxPeak) {
      maxPeak = sample;
    }
  }
  
  // Normalizar se necessário
  if (maxPeak > 0 && maxPeak < 0.95) {
    const normalizeRatio = 0.95 / maxPeak;
    
    for (let i = 0; i < channelData.length; i++) {
      channelData[i] *= normalizeRatio;
    }
  }
  
  return audioBuffer;
}

Compressão Inteligente

# Usando FFmpeg para otimizar áudio
# Converter para formato ideal mantendo qualidade

# MP3 de alta qualidade
ffmpeg -i input.wav -c:a libmp3lame -b:a 192k -ar 48000 output.mp3

# WAV otimizado 
ffmpeg -i input.wav -c:a pcm_s16le -ar 48000 -ac 1 output.wav

# M4A de alta qualidade
ffmpeg -i input.wav -c:a aac -b:a 256k -ar 48000 output.m4a

# Reduzir ruído de fundo
ffmpeg -i input.wav -af "afftdn=nf=-40" output_clean.wav

Casos de Uso Específicos

Consulta Individual

// Configuração para consulta 1:1 (veterinário + dono)
const consultationConfig = {
  environment: 'quiet_room',
  participants: 2,
  microphoneDistance: '20-30cm',
  recordingDuration: '10-30 minutes',
  recommendedFormat: 'WAV 48kHz/16-bit',
  
  settings: {
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true
  }
};

Cirurgia

// Configuração para ambiente cirúrgico
const surgeryConfig = {
  environment: 'operating_room',
  participants: '3-5',
  challenges: ['equipment_noise', 'air_conditioning', 'multiple_speakers'],
  microphoneDistance: '15-25cm',
  recordingDuration: '30-120 minutes',
  recommendedFormat: 'WAV 48kHz/24-bit',
  
  settings: {
    echoCancellation: false,    // Pode interferir com múltiplas vozes
    noiseSuppression: true,
    autoGainControl: false,     // Manter ganho fixo
    manualGain: 0.7
  }
};

Telemedicina

// Configuração para consultas remotas
const telemedicineConfig = {
  environment: 'home_office',
  participants: 2,
  challenges: ['internet_latency', 'compression', 'echo'],
  recordingSource: 'video_call_recording',
  recommendedFormat: 'MP3 192kbps+',
  
  preprocessing: {
    noiseReduction: true,
    volumeNormalization: true,
    echoRemoval: true
  }
};

Resolução de Problemas

Problemas Comuns

Ferramentas de Diagnóstico

// Analisador completo de qualidade de áudio
class AudioQualityAnalyzer {
  static async analyze(audioFile) {
    const audioContext = new AudioContext();
    const arrayBuffer = await audioFile.arrayBuffer();
    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
    
    const analysis = {
      duration: audioBuffer.duration,
      sampleRate: audioBuffer.sampleRate,
      channels: audioBuffer.numberOfChannels,
      quality: this.assessQuality(audioBuffer),
      issues: this.detectIssues(audioBuffer)
    };
    
    return analysis;
  }
  
  static assessQuality(audioBuffer) {
    const channelData = audioBuffer.getChannelData(0);
    
    // Calcular RMS (volume médio)
    let rms = 0;
    for (let i = 0; i < channelData.length; i++) {
      rms += channelData[i] * channelData[i];
    }
    rms = Math.sqrt(rms / channelData.length);
    
    // Calcular SNR estimado
    const snr = this.estimateSNR(channelData);
    
    // Detectar clipping
    const clipping = this.detectClipping(channelData);
    
    let quality = 'good';
    if (rms < 0.01 || snr < 15 || clipping > 0.01) {
      quality = 'poor';
    } else if (rms < 0.05 || snr < 20 || clipping > 0.001) {
      quality = 'fair';
    }
    
    return {
      score: quality,
      rms: rms,
      snr: snr,
      clipping: clipping
    };
  }
  
  static detectIssues(audioBuffer) {
    const issues = [];
    const channelData = audioBuffer.getChannelData(0);
    
    // Volume muito baixo
    const rms = this.calculateRMS(channelData);
    if (rms < 0.01) {
      issues.push({
        type: 'low_volume',
        severity: 'high',
        message: 'Volume muito baixo - aproximar microfone ou aumentar ganho'
      });
    }
    
    // Clipping
    const clipping = this.detectClipping(channelData);
    if (clipping > 0.001) {
      issues.push({
        type: 'clipping',
        severity: 'high',
        message: 'Distorção detectada - reduzir ganho do microfone'
      });
    }
    
    // Duração muito curta
    if (audioBuffer.duration < 10) {
      issues.push({
        type: 'short_duration',
        severity: 'medium',
        message: 'Áudio muito curto - mínimo recomendado: 10 segundos'
      });
    }
    
    return issues;
  }
}

// Uso do analisador
audioInput.addEventListener('change', async (event) => {
  const file = event.target.files[0];
  const analysis = await AudioQualityAnalyzer.analyze(file);
  
  console.log('Análise de qualidade:', analysis);
  
  if (analysis.issues.length > 0) {
    console.warn('Problemas detectados:', analysis.issues);
    // Mostrar alertas para o usuário
  }
});

Melhores Práticas

Antes da Gravação

Preparação do Ambiente

  • ✅ Testar equipamento de áudio
  • ✅ Verificar níveis de ruído
  • ✅ Posicionar microfone corretamente
  • ✅ Orientar participantes sobre fala clara
  • ✅ Configurar software de gravação

Checklist Técnico

  • ✅ Sample rate: 48kHz+
  • ✅ Bit depth: 16-bit+
  • ✅ Formato: WAV ou MP3 192kbps+
  • ✅ Espaço em disco suficiente
  • ✅ Bateria carregada (dispositivos móveis)

Durante a Consulta

  • 🎯 Falar claramente e em ritmo normal
  • 🎯 Evitar interrupções simultâneas
  • 🎯 Monitorar níveis de áudio se possível
  • 🎯 Manter distância consistente do microfone
  • 🎯 Minimizar ruídos de papel, objetos, etc.

Após a Gravação

// Verificação pós-gravação
async function postRecordingCheck(audioFile) {
  const checks = {
    fileSize: audioFile.size > 1024 && audioFile.size < 100 * 1024 * 1024,
    duration: await getAudioDuration(audioFile),
    format: ['mp3', 'wav', 'm4a', 'aac'].includes(getFileExtension(audioFile)),
    quality: await AudioQualityAnalyzer.analyze(audioFile)
  };
  
  const passed = checks.fileSize && 
                 checks.duration >= 10 && 
                 checks.duration <= 3600 &&
                 checks.format &&
                 checks.quality.score !== 'poor';
  
  return {
    passed,
    checks,
    recommendations: generateRecommendations(checks)
  };
}

Próximos Passos