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/
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
"""Adapta o faster-whisper para a transcrição local do Scanner."""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Any, Callable
|
||||
|
||||
from ...scanner.modelos import PalavraDeTranscricao, SegmentoDeTranscricao
|
||||
|
||||
@@ -10,7 +10,8 @@ class ProviderDeTranscricaoLocal:
|
||||
"""Executa transcrição local em lote, sem transmitir a mídia."""
|
||||
|
||||
def __init__(self, modelo: str, dispositivo: str = "cpu", tipo_de_calculo: str = "int8",
|
||||
idioma: str = "pt", tamanho_do_lote: int = 16) -> None:
|
||||
idioma: str = "pt", tamanho_do_lote: int = 16,
|
||||
ao_progresso: Callable[[float], None] | None = None) -> None:
|
||||
"""Carrega o modelo local e configura o tamanho do lote de inferência."""
|
||||
if tamanho_do_lote < 1:
|
||||
raise ValueError("O tamanho do lote deve ser maior que zero.")
|
||||
@@ -22,17 +23,29 @@ class ProviderDeTranscricaoLocal:
|
||||
self.pipeline = BatchedInferencePipeline(model=self.modelo)
|
||||
self.idioma = idioma
|
||||
self.tamanho_do_lote = tamanho_do_lote
|
||||
self.ao_progresso = ao_progresso
|
||||
|
||||
def transcrever(self, clipe: Any) -> list[SegmentoDeTranscricao]:
|
||||
"""Transcreve o áudio com VAD, timestamps e inferência em lote."""
|
||||
arquivo = Path(clipe.arquivo)
|
||||
if not arquivo.is_file():
|
||||
raise FileNotFoundError(f"Arquivo de áudio não encontrado: {arquivo}")
|
||||
segmentos, _ = self.pipeline.transcribe(
|
||||
segmentos, informacoes = self.pipeline.transcribe(
|
||||
str(arquivo), language=self.idioma, vad_filter=True,
|
||||
word_timestamps=True, batch_size=self.tamanho_do_lote,
|
||||
)
|
||||
return [SegmentoDeTranscricao(float(s.start), float(s.end), s.text.strip(),
|
||||
None, tuple(PalavraDeTranscricao(w.word.strip(), float(w.start), float(w.end),
|
||||
getattr(w, "probability", None))
|
||||
for w in (s.words or []) if w.word.strip())) for s in segmentos]
|
||||
duracao = float(getattr(informacoes, "duration", 0.0) or 0.0)
|
||||
resultado: list[SegmentoDeTranscricao] = []
|
||||
for segmento in segmentos:
|
||||
resultado.append(SegmentoDeTranscricao(
|
||||
float(segmento.start), float(segmento.end), segmento.text.strip(),
|
||||
None, tuple(PalavraDeTranscricao(
|
||||
palavra.word.strip(), float(palavra.start), float(palavra.end),
|
||||
getattr(palavra, "probability", None)
|
||||
) for palavra in (segmento.words or []) if palavra.word.strip())
|
||||
))
|
||||
if self.ao_progresso and duracao > 0:
|
||||
self.ao_progresso(min(99.0, max(0.0, float(segmento.end) / duracao * 100)))
|
||||
if self.ao_progresso:
|
||||
self.ao_progresso(100.0)
|
||||
return resultado
|
||||
|
||||
Reference in New Issue
Block a user