Files
jhonny-editor/code/engine/testes/test_provider_de_transcricao_local.py
João Henrique c4c942044f feat: adicionadas métricas opcionais de fala ao Scanner com anális
- adicionadas métricas opcionais de fala ao Scanner com análise acústica na engine
- corrigido o progresso da transcrição do Scanner durante o processamento do Whisper
- refatorado o runner Swift do Apple Vision para executar requests em lote com retry CPU-only, corrigindo falhas de CVPixelBuffer/ANE/OCR
- documentado o fluxo de edição de vídeo por voz integrado ao Scanner, banco e engine
- formalizado o protocolo de edição por chat com perfil editorial e consultas progressivas

Resumo:
- 10 arquivos alterados
- 5 novos
- 5 modificados
- 0 removidos

 5 files changed, 367 insertions(+), 95 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/engine/executar_scanner.py
  - code/engine/integracoes/visual/apple_vision_runner.swift
  - code/engine/integracoes/whisper/provider_de_transcricao_local.py
  - code/engine/testes/test_provider_de_transcricao_local.py
  - .jhonny/analises.db-shm
  - .jhonny/analises.db-wal
  - apple_vision_runner
  - code/relatorios/teste-enquadramento-20s.json
  - docs/
2026-09-09 18:50:00 -04:00

99 lines
3.8 KiB
Python

"""Testes do provider local de transcrição em lote."""
import sys
import tempfile
import types
import unittest
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import patch
from engine.integracoes.whisper import ProviderDeTranscricaoLocal
class TesteDoProviderDeTranscricaoLocal(unittest.TestCase):
"""Verifica a configuração e a conversão dos segmentos do provider."""
def test_usa_pipeline_em_lote_com_vad_e_timestamps_de_palavras(self):
"""Mantém as opções de qualidade ao usar inferência em lote."""
chamadas = {}
class ModeloFalso:
"""Representa o modelo externo durante o teste."""
def __init__(self, *argumentos, **opcoes):
chamadas["modelo"] = (argumentos, opcoes)
class PipelineFalso:
"""Representa o pipeline em lote durante o teste."""
def __init__(self, model):
chamadas["pipeline_modelo"] = model
def transcribe(self, *argumentos, **opcoes):
chamadas["transcricao"] = (argumentos, opcoes)
palavra = SimpleNamespace(word="Olá", start=0.0, end=0.5, probability=0.99)
segmento = SimpleNamespace(start=0.0, end=0.5, text=" Olá ", words=[palavra])
return iter([segmento]), SimpleNamespace(duration=0.5)
modulo_falso = types.SimpleNamespace(
BatchedInferencePipeline=PipelineFalso,
WhisperModel=ModeloFalso,
)
with tempfile.TemporaryDirectory() as pasta:
arquivo = Path(pasta) / "audio.wav"
arquivo.write_bytes(b"audio")
with patch.dict(sys.modules, {"faster_whisper": modulo_falso}):
provider = ProviderDeTranscricaoLocal("small", tamanho_do_lote=8)
resultado = provider.transcrever(SimpleNamespace(arquivo=str(arquivo)))
self.assertEqual(resultado[0].texto, "Olá")
self.assertEqual(chamadas["transcricao"][1]["batch_size"], 8)
self.assertTrue(chamadas["transcricao"][1]["vad_filter"])
self.assertTrue(chamadas["transcricao"][1]["word_timestamps"])
def test_rejeita_tamanho_de_lote_invalido(self):
"""Impede configuração silenciosa de um lote inválido."""
with self.assertRaises(ValueError):
ProviderDeTranscricaoLocal("small", tamanho_do_lote=0)
def test_emite_progresso_conforme_os_segmentos_processados(self):
"""Atualiza o chamador enquanto o gerador do Whisper entrega segmentos."""
progresso = []
class ModeloFalso:
"""Representa o modelo externo durante o teste."""
def __init__(self, *argumentos, **opcoes):
pass
class PipelineFalso:
"""Entrega dois segmentos para simular um áudio em processamento."""
def __init__(self, model):
pass
def transcribe(self, *argumentos, **opcoes):
segmentos = [
SimpleNamespace(start=0.0, end=2.0, text=" um", words=[]),
SimpleNamespace(start=2.0, end=4.0, text=" dois", words=[]),
]
return iter(segmentos), SimpleNamespace(duration=4.0)
modulo_falso = types.SimpleNamespace(
BatchedInferencePipeline=PipelineFalso,
WhisperModel=ModeloFalso,
)
with tempfile.TemporaryDirectory() as pasta:
arquivo = Path(pasta) / "audio.wav"
arquivo.write_bytes(b"audio")
with patch.dict(sys.modules, {"faster_whisper": modulo_falso}):
provider = ProviderDeTranscricaoLocal("small", ao_progresso=progresso.append)
provider.transcrever(SimpleNamespace(arquivo=str(arquivo)))
self.assertEqual(progresso, [50.0, 99.0, 100.0])
if __name__ == "__main__":
unittest.main()