feat: removido o tamanho do modelo do seletor da tela Editar vídeo

- removido o tamanho do modelo do seletor da tela Editar vídeo
- acelerada a transcrição do Scanner com inferência Whisper em lote e cache de hashes
- garantido um resultado separado para cada clipe de áudio selecionado no Scanner
- adicionado cancelamento do processamento do Scanner pela barra de progresso
- exibido estado visual próprio para Scanner cancelado na barra de progresso
- reorganizada a tela Scanner em blocos separados de imagem e som

Resumo:
- 7 arquivos alterados
- 1 novos
- 6 modificados
- 0 removidos

 6 files changed, 92 insertions(+), 40 deletions(-)

Arquivos:
  - .jhonny/analises.db
  - code/cep-plugin/index.html
  - code/cep-plugin/main.js
  - code/cep-plugin/styles.css
  - code/engine/integracoes/whisper/provider_de_transcricao_local.py
  - code/engine/scanner/transcricao_da_timeline.py
  - code/engine/testes/test_provider_de_transcricao_local.py
This commit is contained in:
João Henrique
2026-09-09 16:57:29 -04:00
parent 245dcd8015
commit 53a8307f38
7 changed files with 154 additions and 40 deletions
@@ -1,3 +1,5 @@
"""Adapta o faster-whisper para a transcrição local do Scanner."""
from pathlib import Path
from typing import Any
@@ -5,23 +7,31 @@ from ...scanner.modelos import PalavraDeTranscricao, SegmentoDeTranscricao
class ProviderDeTranscricaoLocal:
"""Provider local usando faster-whisper, sem transmitir mídia."""
"""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") -> None:
idioma: str = "pt", tamanho_do_lote: int = 16) -> 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.")
self.nome_do_modelo = Path(modelo).name
if "faster-whisper-" in modelo:
self.nome_do_modelo = modelo.split("faster-whisper-", 1)[1].split("/", 1)[0]
from faster_whisper import WhisperModel
from faster_whisper import BatchedInferencePipeline, WhisperModel
self.modelo = WhisperModel(modelo, device=dispositivo, compute_type=tipo_de_calculo)
self.pipeline = BatchedInferencePipeline(model=self.modelo)
self.idioma = idioma
self.tamanho_do_lote = tamanho_do_lote
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.modelo.transcribe(str(arquivo), language=self.idioma,
vad_filter=True, word_timestamps=True)
segmentos, _ = 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))