feat: criado repositório jhonny-editor no Gitea
criado repositório jhonny-editor no Gitea adicionado script admin/deploy.command com commit automático atualizado admin/DEV-NOTES.md com template limpo Resumo: - 48 arquivos alterados - 26 novos - 19 modificados - 3 removidos 22 files changed, 658 insertions(+), 568 deletions(-) Arquivos: - AGENTS.md - admin/DEV-NOTES.md - admin/OpenCut.command - admin/commit.command - admin/deploy.command - admin/update.command - code/cep-plugin/index.html - code/cep-plugin/main.js - code/cep-plugin/styles.css - code/engine/ARQUITETURA.md - code/engine/arquitetura/README.md - code/engine/gerar_relatorio_timeline.py - code/engine/integracoes/apple_speech/apple_speech_transcriber.swift - code/engine/integracoes/apple_speech/provider_de_transcricao_apple.py - code/engine/integracoes/midia/__init__.py - code/engine/integracoes/whisper/provider_de_transcricao_local.py - code/engine/scanner/__init__.py - code/engine/scanner/coordenacao/__init__.py - code/engine/scanner/descoberta/__init__.py - code/engine/scanner/modelos.py - code/engine/scanner/transcricao_da_timeline.py - code/src/tools/discovery.ts - :memory:.ses - admin/Jhonny.command - admin/inativos/OpenCut.command - admin/inativos/update.command - code/docs/glossario-analise-emocional.md - code/docs/levantamento-apple-vision-e-apple-intelligence.md - code/docs/levantamento-ferramentas-analise-visual-local.md - code/engine/arquitetura/biblioteca-inteligente-de-videos.md - code/engine/executar_scanner.py - code/engine/integracoes/huggingface/ - code/engine/integracoes/midia/extracao_de_metadados.py - code/engine/integracoes/visual/ - code/engine/requirements-visual.txt - code/engine/scanner/configuracao_visual.py - code/engine/scanner/descoberta/descoberta_de_arquivos.py - code/engine/scanner/metadados.py - code/engine/scanner/relatorio_visual.py - code/engine/scanner/retakes/ - code/engine/scanner/visual.py - code/engine/testes/test_analise_visual_local.py - code/engine/testes/test_arquivos_e_metadados.py - code/engine/testes/test_provider_de_transcricao_apple.py - code/relatorios/analise-brools/ - code/relatorios/analise-visual/ - code/relatorios/audio/arquivos/ - code/relatorios/transcricao-timeline.md
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
"""Converte a transcrição existente em falas ordenadas para a análise.
|
||||
|
||||
O módulo de retakes não realiza transcrição. Ele recebe a saída do
|
||||
``TranscricaoDaTimeline`` (lista de ``TranscricaoDoClipe``) e a converte
|
||||
em ``Fala``s ordenadas ao longo da timeline, preservando o vínculo com o
|
||||
segmento/clipe de origem e as palavras alinhadas quando disponíveis.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Iterable
|
||||
|
||||
from ..transcricao_da_timeline import TranscricaoDoClipe
|
||||
from .modelos_de_retakes import Fala
|
||||
|
||||
# Sinais de erro mais comuns vindos dos providers de transcrição.
|
||||
_PALAVRAS_DE_ERRO = {"", "...", "…"}
|
||||
|
||||
_VOYELS = "aeiouáéíóúâêôãõàèìòù"
|
||||
_CONSOANTES = "bcdfghjklmnpqrstvwxyz"
|
||||
_PADRAO_SILABA = re.compile(
|
||||
rf"([{_VOYELS}][^aeiouáéíóúâêôãõàèìòù]*)|([{_CONSOANTES}]+[aeiouáéíóúâêôãõàèìòù]?)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def _normalizar(texto: str) -> str:
|
||||
"""Minúsculas, sem pontuação e sem espaços duplicados."""
|
||||
sem_pontuacao = re.sub(r"[^\w\s]", " ", texto)
|
||||
return " ".join(sem_pontuacao.lower().split())
|
||||
|
||||
|
||||
def _prefixo_comum(a: list[str], b: list[str]) -> int:
|
||||
n = 0
|
||||
for x, y in zip(a, b):
|
||||
if x != y:
|
||||
break
|
||||
n += 1
|
||||
return n
|
||||
|
||||
|
||||
def _sucesso_de_silabas(a: list[str], b: list[str]) -> float:
|
||||
if not a or not b:
|
||||
return 0.0
|
||||
silabas_a = [_PADRAO_SILABA.findall(p)[0][0] for p in a]
|
||||
silabas_b = [_PADRAO_SILABA.findall(p)[0][0] for p in b]
|
||||
n = _prefixo_comum(silabas_a, silabas_b)
|
||||
return n / max(len(silabas_a), len(silabas_b))
|
||||
|
||||
|
||||
def _e_ruido(texto: str) -> bool:
|
||||
texto_limpo = _normalizar(texto)
|
||||
if texto_limpo in _PALAVRAS_DE_ERRO:
|
||||
return True
|
||||
# Fala em branco ou "vazia" por provedor.
|
||||
return not texto_limpo
|
||||
|
||||
|
||||
class AdaptadorDeFalas:
|
||||
"""Transforma a transcrição da timeline em falas prontas para análise.
|
||||
|
||||
Recebe uma coleção de ``TranscricaoDoClipe`` (uma por faixa de áudio do
|
||||
vídeo) e devolve as falas ordenadas por tempo. O ``video_id`` é um rótulo
|
||||
informado pelo chamador; quando ausente, usa o identificador da timeline.
|
||||
"""
|
||||
|
||||
def __init__(self, video_id: str | None = None, faixa_id: str | None = None) -> None:
|
||||
self.video_id = video_id
|
||||
self.faixa_id = faixa_id
|
||||
|
||||
def converter(
|
||||
self,
|
||||
transcricoes: Iterable[TranscricaoDoClipe],
|
||||
video_id: str | None = None,
|
||||
faixa_id: str | None = None,
|
||||
) -> list[Fala]:
|
||||
video_id = video_id or self.video_id or "video"
|
||||
faixa_id = faixa_id or self.faixa_id or "faixa"
|
||||
|
||||
falas: list[Fala] = []
|
||||
for transcricao in transcricoes:
|
||||
segmento_id = transcricao.identificador_do_clipe
|
||||
for segmento in transcricao.segmentos:
|
||||
if _e_ruido(segmento.texto):
|
||||
continue
|
||||
falas.append(Fala(
|
||||
id=f"{segmento_id}:{segmento.inicio:.3f}",
|
||||
video_id=video_id,
|
||||
faixa_id=faixa_id,
|
||||
segmento_id=segmento_id,
|
||||
ordem=-1, # preenchida após a ordenação
|
||||
inicio=segmento.inicio,
|
||||
fim=segmento.fim,
|
||||
texto=segmento.texto,
|
||||
texto_normalizado=_normalizar(segmento.texto),
|
||||
palavras=segmento.palavras,
|
||||
falante=segmento.falante,
|
||||
))
|
||||
|
||||
falas.sort(key=lambda item: (item.inicio, item.fim))
|
||||
for indice, fala in enumerate(falas):
|
||||
falas[indice] = Fala(
|
||||
id=fala.id,
|
||||
video_id=fala.video_id,
|
||||
faixa_id=fala.faixa_id,
|
||||
segmento_id=fala.segmento_id,
|
||||
ordem=indice,
|
||||
inicio=fala.inicio,
|
||||
fim=fala.fim,
|
||||
texto=fala.texto,
|
||||
texto_normalizado=fala.texto_normalizado,
|
||||
palavras=fala.palavras,
|
||||
falante=fala.falante,
|
||||
)
|
||||
return falas
|
||||
Reference in New Issue
Block a user