feat: criada a aba Tipos de vídeo com cinco perfis editoriais pré-
- criada a aba Tipos de vídeo com cinco perfis editoriais pré-cadastrados e catálogo local pronto para integração com o Schedule Light - ampliado o cadastro vertical dos perfis com objetivos, narrativa, emoção, prioridades, formato, áudio e regras para IA - criado plano JSON para resumir a entrevista jornalística em até três minutos Resumo: - 4 arquivos alterados - 1 novos - 3 modificados - 0 removidos 3 files changed, 318 insertions(+), 3 deletions(-) Arquivos: - code/cep-plugin/index.html - code/cep-plugin/main.js - code/cep-plugin/styles.css - plano-resumo-video.json
This commit is contained in:
@@ -34,6 +34,9 @@
|
|||||||
<button class="tab-button" id="tabBtnAnalises" role="tab" aria-selected="false" aria-controls="tabAnalises" onclick="switchTab('analises')" type="button">
|
<button class="tab-button" id="tabBtnAnalises" role="tab" aria-selected="false" aria-controls="tabAnalises" onclick="switchTab('analises')" type="button">
|
||||||
<span class="tab-icon" aria-hidden="true">⎘</span>Análises
|
<span class="tab-icon" aria-hidden="true">⎘</span>Análises
|
||||||
</button>
|
</button>
|
||||||
|
<button class="tab-button" id="tabBtnTiposVideo" role="tab" aria-selected="false" aria-controls="tabTiposVideo" onclick="switchTab('tipos-video')" type="button">
|
||||||
|
<span class="tab-icon" aria-hidden="true">▦</span>Tipos de vídeo
|
||||||
|
</button>
|
||||||
<button class="tab-button" id="tabBtnBridge" role="tab" aria-selected="false" aria-controls="tabBridge" onclick="switchTab('bridge')" type="button">
|
<button class="tab-button" id="tabBtnBridge" role="tab" aria-selected="false" aria-controls="tabBridge" onclick="switchTab('bridge')" type="button">
|
||||||
<span class="tab-icon" aria-hidden="true">⇄</span>Conexão
|
<span class="tab-icon" aria-hidden="true">⇄</span>Conexão
|
||||||
</button>
|
</button>
|
||||||
@@ -374,6 +377,76 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- =========================== TIPOS DE VÍDEO =========================== -->
|
||||||
|
<div class="tab-panel" id="tabTiposVideo" role="tabpanel" aria-labelledby="tabBtnTiposVideo" hidden>
|
||||||
|
<p class="tab-intro">Cadastre o padrão editorial que a IA e o editor devem seguir para cada tipo de vídeo. As alterações ficam salvas no catálogo local do Schedule Light.</p>
|
||||||
|
|
||||||
|
<section class="card">
|
||||||
|
<div class="card-head">
|
||||||
|
<h2>Catálogo de tipos</h2>
|
||||||
|
<button class="link-button" onclick="tipoVideoNovo()" type="button">+ Novo tipo</button>
|
||||||
|
</div>
|
||||||
|
<div id="tiposVideoLista" class="video-type-list" role="list" aria-label="Tipos de vídeo cadastrados"></div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="card" id="tipoVideoEditorCard" hidden>
|
||||||
|
<div class="card-head"><h2 id="tipoVideoEditorTitulo">Novo tipo de vídeo</h2><span class="card-kicker" id="tipoVideoEditorStatus">Rascunho</span></div>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>1</span><div><strong>Identificação</strong><small>Nome, categoria e status do perfil.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoNome">Nome do perfil</label><input class="text-field" id="tipoVideoNome" type="text" placeholder="Ex.: Depoimento de cliente">
|
||||||
|
<label class="field-label" for="tipoVideoDescricao">Descrição</label><textarea id="tipoVideoDescricao" rows="2" placeholder="Para que este vídeo existe e qual resultado deve provocar?"></textarea>
|
||||||
|
<div class="field-grid"><div><label class="field-label" for="tipoVideoCategoria">Categoria</label><select class="select-field" id="tipoVideoCategoria"><option>Depoimento</option><option>Entrevista</option><option>Storytelling</option><option>Educativo</option><option>Comercial</option><option>Institucional</option></select></div><div><label class="field-label" for="tipoVideoAtivo">Status</label><label class="checkbox-field"><input id="tipoVideoAtivo" type="checkbox"><span>Perfil ativo</span></label></div></div>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>2</span><div><strong>Objetivo</strong><small>O resultado que o vídeo deve provocar.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoObjetivo">Objetivo principal</label><input class="text-field" id="tipoVideoObjetivo" type="text" placeholder="Ex.: Gerar confiança e credibilidade">
|
||||||
|
<label class="field-label" for="tipoVideoObjetivoSecundario">Objetivo secundário</label><input class="text-field" id="tipoVideoObjetivoSecundario" type="text" placeholder="Ex.: Criar conexão emocional">
|
||||||
|
<label class="field-label" for="tipoVideoPublico">Público-alvo</label><input class="text-field" id="tipoVideoPublico" type="text" placeholder="Ex.: Clientes em potencial">
|
||||||
|
<label class="field-label" for="tipoVideoMensagem">Mensagem principal</label><textarea id="tipoVideoMensagem" rows="2" placeholder="Qual mensagem precisa permanecer depois que o vídeo terminar?"></textarea>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>3</span><div><strong>Narrativa</strong><small>Como a história deve ser organizada.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoTipoNarrativa">Tipo de narrativa</label><select class="select-field" id="tipoVideoTipoNarrativa"><option>História pessoal</option><option>Pergunta e resposta</option><option>Jornada / transformação</option><option>Explicação passo a passo</option><option>Problema → solução → benefício</option></select>
|
||||||
|
<label class="field-label" for="tipoVideoFocoNarrativo">Foco narrativo</label><input class="text-field" id="tipoVideoFocoNarrativo" type="text" placeholder="Ex.: Problema → solução → resultado">
|
||||||
|
<label class="checkbox-field"><input id="tipoVideoStorytelling" type="checkbox"><span>Priorizar storytelling</span></label>
|
||||||
|
<label class="field-label" for="tipoVideoEstrutura">Estrutura narrativa</label><textarea id="tipoVideoEstrutura" rows="3" placeholder="Ex.: Gancho → contexto → desenvolvimento → conclusão."></textarea>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>4</span><div><strong>Emoção</strong><small>Qual sensação deve ser construída.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoEmocao">Objetivo emocional</label><input class="text-field" id="tipoVideoEmocao" type="text" placeholder="Confiança, empatia, curiosidade…">
|
||||||
|
<label class="field-label" for="tipoVideoIntensidade">Intensidade emocional <output id="tipoVideoIntensidadeValor">3 / 5</output></label><input id="tipoVideoIntensidade" type="range" min="1" max="5" step="1" value="3" oninput="tipoVideoAtualizarIntensidade()">
|
||||||
|
<label class="field-label" for="tipoVideoTom">Tom emocional</label><select class="select-field" id="tipoVideoTom"><option>Positivo</option><option>Inspirador</option><option>Íntimo</option><option>Informativo</option><option>Urgente</option><option>Contemplativo</option></select>
|
||||||
|
<label class="field-label" for="tipoVideoConstrucaoEmocao">Como construir a emoção</label><textarea id="tipoVideoConstrucaoEmocao" rows="2" placeholder="Ex.: Pausas naturais, B-roll real e trilha discreta."></textarea>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>5</span><div><strong>Formato</strong><small>Onde e em quanto tempo o vídeo será consumido.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoCanais">Formato / canal</label><input class="text-field" id="tipoVideoCanais" type="text" placeholder="Instagram Reels, TikTok, YouTube…">
|
||||||
|
<label class="field-label" for="tipoVideoProporcao">Orientação preferencial</label><select class="select-field" id="tipoVideoProporcao"><option value="9:16">9:16 — vertical</option><option value="1:1">1:1 — quadrado</option><option value="16:9">16:9 — horizontal</option><option value="adaptavel">Adaptável</option></select>
|
||||||
|
<div class="field-grid"><div><label class="field-label" for="tipoVideoDuracaoMinima">Duração mínima (segundos)</label><input class="text-field" id="tipoVideoDuracaoMinima" type="number" min="0" step="1"></div><div><label class="field-label" for="tipoVideoDuracao">Duração máxima (segundos)</label><input class="text-field" id="tipoVideoDuracao" type="number" min="1" step="1"></div></div>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>6</span><div><strong>Prioridades</strong><small>Ordem de importância quando houver conflito.</small></div></div>
|
||||||
|
<div id="tipoVideoPrioridades" class="priority-list"></div>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>7</span><div><strong>Elementos de edição</strong><small>O que deve ou não aparecer na montagem.</small></div></div>
|
||||||
|
<label class="checkbox-field"><input id="tipoVideoUsaBroll" type="checkbox"><span>Usar B-roll</span></label><label class="checkbox-field"><input id="tipoVideoUsaLegendas" type="checkbox"><span>Usar legendas</span></label><label class="checkbox-field"><input id="tipoVideoUsaTextos" type="checkbox"><span>Usar textos e títulos</span></label><label class="checkbox-field"><input id="tipoVideoUsaGraficos" type="checkbox"><span>Usar gráficos ou telas explicativas</span></label><label class="checkbox-field"><input id="tipoVideoUsaZoom" type="checkbox"><span>Usar zooms e reenquadramentos</span></label>
|
||||||
|
<label class="field-label" for="tipoVideoCortes">Critério de cortes</label><textarea id="tipoVideoCortes" rows="3" placeholder="O que cortar, preservar ou acelerar?"></textarea>
|
||||||
|
<label class="field-label" for="tipoVideoBroll">Orientação de B-roll</label><textarea id="tipoVideoBroll" rows="3" placeholder="Quando usar imagens de apoio e com qual função?"></textarea>
|
||||||
|
<label class="field-label" for="tipoVideoTexto">Textos, títulos e legendas</label><textarea id="tipoVideoTexto" rows="3" placeholder="Legendas, palavras-chave, títulos, CTA…"></textarea>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>8</span><div><strong>Áudio</strong><small>Como a voz, música e efeitos devem conviver.</small></div></div>
|
||||||
|
<label class="checkbox-field"><input id="tipoVideoUsaMusica" type="checkbox"><span>Usar música</span></label><label class="field-label" for="tipoVideoIntensidadeMusica">Intensidade da música</label><input id="tipoVideoIntensidadeMusica" type="range" min="0" max="100" step="5" value="30" oninput="tipoVideoAtualizarIntensidadeMusica()"><output id="tipoVideoIntensidadeMusicaValor">30%</output>
|
||||||
|
<label class="field-label" for="tipoVideoPrioridadeVoz">Prioridade da voz</label><select class="select-field" id="tipoVideoPrioridadeVoz"><option>Alta</option><option>Muito alta</option><option>Equilibrada</option></select>
|
||||||
|
<label class="field-label" for="tipoVideoSom">Tratamento de áudio</label><textarea id="tipoVideoSom" rows="3" placeholder="Trilha, volume, pausas, limpeza e ênfase."></textarea>
|
||||||
|
</section>
|
||||||
|
<section class="profile-section"><div class="profile-section-head"><span>9</span><div><strong>Regras e instruções para IA</strong><small>Critérios que devem orientar o plano de edição.</small></div></div>
|
||||||
|
<label class="field-label" for="tipoVideoDiretriz">Regras de edição</label><textarea id="tipoVideoDiretriz" rows="5" placeholder="Uma regra por linha. Ex.: Preservar a naturalidade da fala."></textarea>
|
||||||
|
<label class="field-label" for="tipoVideoRestricoes">Restrições de edição</label><textarea id="tipoVideoRestricoes" rows="3" placeholder="O que a IA não deve fazer?"></textarea>
|
||||||
|
<label class="field-label" for="tipoVideoQualidade">Critérios de qualidade</label><textarea id="tipoVideoQualidade" rows="3" placeholder="Como saberemos que o resultado ficou bom?"></textarea>
|
||||||
|
</section>
|
||||||
|
<div class="button-row">
|
||||||
|
<button class="button button-primary" onclick="tipoVideoSalvar()" type="button">Salvar tipo</button>
|
||||||
|
<button class="button button-ghost" onclick="tipoVideoCancelar()" type="button">Cancelar</button>
|
||||||
|
<button class="button button-ghost" onclick="tipoVideoCopiarJson()" type="button">Copiar JSON para IA</button>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<p class="field-help" id="tiposVideoStatus">—</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- ============================== CONEXÃO ============================== -->
|
<!-- ============================== CONEXÃO ============================== -->
|
||||||
|
|||||||
@@ -30,6 +30,28 @@ function log(msg, cls) {
|
|||||||
// reposicionado na aba de origem com etapa atual, barra e tempo decorrido.
|
// reposicionado na aba de origem com etapa atual, barra e tempo decorrido.
|
||||||
var taskState = { active: false, startedAt: 0, timer: null, clearTimer: null, mirror: null, originTab: "silence", originPanelId: "tabSilence", errorText: "" };
|
var taskState = { active: false, startedAt: 0, timer: null, clearTimer: null, mirror: null, originTab: "silence", originPanelId: "tabSilence", errorText: "" };
|
||||||
|
|
||||||
|
var TIPOS_VIDEO_CHAVE = "schedule_light_tipos_video";
|
||||||
|
var tipoVideoAtualId = null;
|
||||||
|
var tiposVideoPadrao = [
|
||||||
|
{ id: "midia-social", nome: "Conteúdo para mídia social", duracao_maxima_segundos: 60, descricao: "Vídeo curto para interromper a rolagem, comunicar uma ideia e estimular uma ação.", canais: "Instagram Reels, TikTok, Shorts", proporcao: "9:16", ritmo: "agil", emocao: "Curiosidade e energia", storytelling: true, estrutura: "Gancho nos primeiros 2 segundos → desenvolvimento em blocos curtos → CTA direto.", cortes: "Cortes rápidos, remover pausas e repetições; preservar frases de impacto. Usar jump cuts com moderação.", broll: "Inserir imagens de apoio a cada mudança de ideia, preferindo planos que reforcem a fala.", texto: "Legendas sempre; destacar palavras-chave na tela e usar título curto. CTA visual no final.", som: "Voz sempre inteligível e à frente da trilha; música energética em volume baixo.", diretriz: "Priorize retenção e clareza. Cada corte deve manter o ritmo e reforçar uma única ideia por vez." },
|
||||||
|
{ id: "depoimento", nome: "Depoimento de cliente", duracao_maxima_segundos: 120, descricao: "Relato autêntico que gera identificação, confiança e prova social.", canais: "Site, redes sociais, apresentação comercial", proporcao: "adaptavel", ritmo: "equilibrado", emocao: "Empatia e confiança", storytelling: true, estrutura: "Problema vivido → experiência com a solução → transformação → recomendação.", cortes: "Cortar hesitações e desvios sem deixar a fala artificial; manter reações, pausas emocionais e frases espontâneas.", broll: "Cobrir cortes com cenas do cliente usando o produto, ambiente real ou detalhes que comprovem o relato.", texto: "Nome e contexto do depoente; destacar a transformação em frases curtas; legendas completas.", som: "Voz natural, limpa e próxima; trilha emocional discreta, crescendo apenas na transformação.", diretriz: "Proteja a autenticidade do depoimento. A emoção deve vir da fala e das evidências, não de efeitos excessivos." },
|
||||||
|
{ id: "entrevista", nome: "Entrevista", duracao_maxima_segundos: 600, descricao: "Conversa estruturada para extrair conhecimento, opinião ou história de uma pessoa.", canais: "YouTube, podcast em vídeo, cortes sociais", proporcao: "16:9", ritmo: "equilibrado", emocao: "Interesse e credibilidade", storytelling: true, estrutura: "Apresentação → perguntas essenciais → aprofundamento → síntese e encerramento.", cortes: "Remover redundâncias e silêncios longos; preservar respostas completas, escuta, reação e contexto da pergunta.", broll: "Usar planos de reação, detalhes do ambiente e imagens relacionadas ao tema para quebrar a monotonia.", texto: "Identificação do entrevistado, perguntas resumidas quando necessário, capítulos ou palavras-chave.", som: "Diálogo consistente entre os canais; reduzir ruído e nivelar vozes sem tirar naturalidade.", diretriz: "Mantenha a linha de raciocínio da conversa. Não cortar uma resposta de modo que altere o sentido ou a intenção do entrevistado." },
|
||||||
|
{ id: "institucional", nome: "Vídeo institucional", duracao_maxima_segundos: 180, descricao: "Apresentação da empresa, marca, cultura ou solução com percepção de valor.", canais: "Site, eventos, apresentações, LinkedIn", proporcao: "16:9", ritmo: "progressivo", emocao: "Segurança e inspiração", storytelling: true, estrutura: "Contexto ou propósito → pessoas e operação → diferenciais → prova → convite para conhecer.", cortes: "Ritmo elegante; evitar excesso de cortes. Alternar entrevistas, planos de ambiente e detalhes de operação.", broll: "B-roll planejado para mostrar pessoas, processos, produto e escala; toda imagem deve provar uma mensagem.", texto: "Títulos limpos, dados essenciais e assinatura da marca; evitar excesso de texto na tela.", som: "Trilha cinematográfica ou institucional discreta; voz firme, clara e com pausas bem preservadas.", diretriz: "Construa confiança e percepção de valor. Use consistência visual e sonora; efeitos só quando ajudarem a mensagem da marca." },
|
||||||
|
{ id: "educativo-storytelling", nome: "Educativo com storytelling", duracao_maxima_segundos: 240, descricao: "Explicação didática que ensina uma ideia por meio de uma história, caso ou problema concreto.", canais: "YouTube, curso, LinkedIn, redes sociais", proporcao: "adaptavel", ritmo: "progressivo", emocao: "Curiosidade e clareza", storytelling: true, estrutura: "Problema ou pergunta → história/exemplo → explicação → aplicação prática → resumo.", cortes: "Cortar repetições, mas manter a sequência pedagógica; inserir pausas após conceitos importantes.", broll: "Usar diagramas, tela, exemplos e imagens que tornem o conceito visível; sincronizar apoio com a explicação.", texto: "Título do conceito, palavras-chave e resumo final; legendas e marcadores de etapas.", som: "Voz em primeiro plano; trilha quase imperceptível; pequenos efeitos apenas para sinalizar transições.", diretriz: "Ensine uma coisa por vez. O espectador deve entender o conceito sem depender apenas de texto ou de efeitos visuais." }
|
||||||
|
];
|
||||||
|
|
||||||
|
function tipoVideoCompletar(tipo) {
|
||||||
|
var configuracoes = {
|
||||||
|
"midia-social": { categoria: "Comercial", objetivo: "Gerar retenção e ação", objetivo_secundario: "Comunicar uma ideia rapidamente", publico: "Público das redes sociais", mensagem: "Uma ideia clara por vídeo.", tipo_narrativa: "Problema → solução → benefício", foco_narrativo: "Gancho e CTA", intensidade: 4, tom: "Positivo", construcao_emocao: "Ritmo ágil, cortes de impacto, legendas e trilha energética.", duracao_minima: 15, prioridades: ["Retenção", "Clareza", "Mensagem", "Ritmo", "Estética"], usa_broll: true, usa_legendas: true, usa_textos: true, usa_graficos: false, usa_zoom: true, usa_musica: true, intensidade_musica: 25, prioridade_voz: "Muito alta", restricoes: "Evitar excesso de informação e cortes sem função.", qualidade: "A abertura prende atenção e a mensagem é compreendida sem áudio." },
|
||||||
|
"depoimento": { categoria: "Depoimento", objetivo: "Gerar credibilidade e confiança", objetivo_secundario: "Criar identificação emocional", publico: "Clientes em potencial", mensagem: "A experiência real comprova o valor da solução.", tipo_narrativa: "História pessoal", foco_narrativo: "Problema → experiência → transformação → recomendação", intensidade: 3, tom: "Íntimo", construcao_emocao: "Preservar pausas naturais, reações e imagens reais; usar trilha discreta.", duracao_minima: 30, prioridades: ["Autenticidade", "Clareza", "Conexão emocional", "Ritmo", "Estética"], usa_broll: true, usa_legendas: true, usa_textos: true, usa_graficos: false, usa_zoom: false, usa_musica: true, intensidade_musica: 20, prioridade_voz: "Muito alta", restricoes: "Não alterar o sentido das frases nem deixar o depoimento artificial.", qualidade: "A pessoa parece verdadeira e o resultado do relato fica evidente." },
|
||||||
|
"entrevista": { categoria: "Entrevista", objetivo: "Transmitir conhecimento e autoridade", objetivo_secundario: "Organizar a conversa por temas", publico: "Pessoas interessadas no assunto", mensagem: "O conteúdo da conversa é compreendido com contexto.", tipo_narrativa: "Pergunta e resposta", foco_narrativo: "Pergunta → resposta → aprofundamento", intensidade: 2, tom: "Informativo", construcao_emocao: "Reações, escuta e pausas que preservem a naturalidade da conversa.", duracao_minima: 60, prioridades: ["Clareza", "Conteúdo", "Contexto", "Ritmo", "Estética"], usa_broll: true, usa_legendas: true, usa_textos: true, usa_graficos: false, usa_zoom: true, usa_musica: false, intensidade_musica: 10, prioridade_voz: "Muito alta", restricoes: "Não cortar frases de modo que prejudique o raciocínio do entrevistado.", qualidade: "As respostas mantêm contexto, lógica e informação relevante." },
|
||||||
|
"institucional": { categoria: "Institucional", objetivo: "Apresentar valor e confiança na marca", objetivo_secundario: "Mostrar pessoas, processo e diferenciais", publico: "Clientes, parceiros e equipe", mensagem: "A marca entrega valor de forma consistente.", tipo_narrativa: "Jornada / transformação", foco_narrativo: "Propósito → pessoas → operação → prova", intensidade: 4, tom: "Inspirador", construcao_emocao: "Trilha progressiva, imagens de pessoas e planos de operação.", duracao_minima: 45, prioridades: ["Confiança", "Mensagem", "Narrativa", "Estética", "Ritmo"], usa_broll: true, usa_legendas: true, usa_textos: true, usa_graficos: true, usa_zoom: false, usa_musica: true, intensidade_musica: 35, prioridade_voz: "Alta", restricoes: "Evitar efeitos decorativos que não reforcem a mensagem da marca.", qualidade: "O vídeo transmite profissionalismo, clareza e percepção de valor." },
|
||||||
|
"educativo-storytelling": { categoria: "Educativo", objetivo: "Ensinar um assunto com clareza", objetivo_secundario: "Aumentar retenção e aplicação prática", publico: "Pessoas que precisam aprender o assunto", mensagem: "O espectador consegue entender e aplicar o conceito.", tipo_narrativa: "Explicação passo a passo", foco_narrativo: "Problema → exemplo → explicação → aplicação", intensidade: 2, tom: "Informativo", construcao_emocao: "Curiosidade inicial, exemplos visuais e pausas após conceitos importantes.", duracao_minima: 60, prioridades: ["Clareza", "Organização", "Didática", "Retenção", "Estética"], usa_broll: true, usa_legendas: true, usa_textos: true, usa_graficos: true, usa_zoom: true, usa_musica: false, intensidade_musica: 5, prioridade_voz: "Muito alta", restricoes: "Não cortar exemplos ou transições que prejudiquem a explicação.", qualidade: "O conteúdo fica fácil de acompanhar, revisar e aplicar." }
|
||||||
|
}[tipo.id] || {};
|
||||||
|
var completo = Object.assign({ ativo: true, categoria: "Personalizado", objetivo: "", objetivo_secundario: "", publico: "", mensagem: "", tipo_narrativa: "História pessoal", foco_narrativo: "", intensidade: 3, tom: "Positivo", construcao_emocao: "", duracao_minima: 0, prioridades: ["Clareza", "Mensagem", "Ritmo", "Conexão emocional", "Estética"], usa_broll: false, usa_legendas: true, usa_textos: false, usa_graficos: false, usa_zoom: false, usa_musica: false, intensidade_musica: 20, prioridade_voz: "Alta", restricoes: "", qualidade: "" }, configuracoes, tipo);
|
||||||
|
return completo;
|
||||||
|
}
|
||||||
|
|
||||||
function taskEl(id) { return document.getElementById(id); }
|
function taskEl(id) { return document.getElementById(id); }
|
||||||
|
|
||||||
function formatClock(ms) {
|
function formatClock(ms) {
|
||||||
@@ -207,6 +229,7 @@ function switchTab(name) {
|
|||||||
{ key: "scanner", panel: "tabScanner", btn: "tabBtnScanner" },
|
{ key: "scanner", panel: "tabScanner", btn: "tabBtnScanner" },
|
||||||
{ key: "retakes", panel: "tabRetakes", btn: "tabBtnRetakes" },
|
{ key: "retakes", panel: "tabRetakes", btn: "tabBtnRetakes" },
|
||||||
{ key: "analises", panel: "tabAnalises", btn: "tabBtnAnalises" },
|
{ key: "analises", panel: "tabAnalises", btn: "tabBtnAnalises" },
|
||||||
|
{ key: "tipos-video", panel: "tabTiposVideo", btn: "tabBtnTiposVideo" },
|
||||||
{ key: "bridge", panel: "tabBridge", btn: "tabBtnBridge" },
|
{ key: "bridge", panel: "tabBridge", btn: "tabBtnBridge" },
|
||||||
{ key: "models", panel: "tabModels", btn: "tabBtnModels" },
|
{ key: "models", panel: "tabModels", btn: "tabBtnModels" },
|
||||||
{ key: "settings", panel: "tabSettings", btn: "tabBtnSettings" },
|
{ key: "settings", panel: "tabSettings", btn: "tabBtnSettings" },
|
||||||
@@ -226,6 +249,196 @@ function switchTab(name) {
|
|||||||
if (name === "scanner") { renderScannerTranscriptionOptions(); loadScannerProfile(); renderScannerHuggingFaceStatus(); }
|
if (name === "scanner") { renderScannerTranscriptionOptions(); loadScannerProfile(); renderScannerHuggingFaceStatus(); }
|
||||||
if (name === "retakes") retakesAoAbrir();
|
if (name === "retakes") retakesAoAbrir();
|
||||||
if (name === "analises") analisesAoAbrir();
|
if (name === "analises") analisesAoAbrir();
|
||||||
|
if (name === "tipos-video") tiposVideoAoAbrir();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Catálogo de tipos de vídeo -------------------------------------------
|
||||||
|
// A primeira versão usa o armazenamento local do painel. O documento salvo já
|
||||||
|
// tem formato estável e pode ser migrado para o Schedule Light sem alterar o
|
||||||
|
// contrato editorial enviado para a IA.
|
||||||
|
function tiposVideoLer() {
|
||||||
|
try {
|
||||||
|
var salvo = JSON.parse(localStorage.getItem(TIPOS_VIDEO_CHAVE) || "null");
|
||||||
|
if (Array.isArray(salvo) && salvo.length) return salvo.map(tipoVideoCompletar);
|
||||||
|
var iniciais = tiposVideoPadrao.slice().map(tipoVideoCompletar);
|
||||||
|
tiposVideoSalvarNoCatalogo(iniciais);
|
||||||
|
return iniciais;
|
||||||
|
} catch (_) { return tiposVideoPadrao.slice().map(tipoVideoCompletar); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function tiposVideoSalvarNoCatalogo(lista) {
|
||||||
|
localStorage.setItem(TIPOS_VIDEO_CHAVE, JSON.stringify(lista));
|
||||||
|
}
|
||||||
|
|
||||||
|
function tiposVideoAoAbrir() {
|
||||||
|
tiposVideoRenderizarLista();
|
||||||
|
if (!tipoVideoAtualId) tipoVideoNovo();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tiposVideoRenderizarLista() {
|
||||||
|
var lista = document.getElementById("tiposVideoLista");
|
||||||
|
if (!lista) return;
|
||||||
|
lista.innerHTML = "";
|
||||||
|
tiposVideoLer().forEach(function (tipo) {
|
||||||
|
var item = document.createElement("div");
|
||||||
|
item.className = "video-type-row" + (tipo.id === tipoVideoAtualId ? " is-selected" : "");
|
||||||
|
item.setAttribute("role", "listitem");
|
||||||
|
item.innerHTML = '<div class="video-type-copy"><strong></strong><span></span></div><div class="video-type-meta"></div><button class="button button-ghost" type="button">Editar</button>';
|
||||||
|
item.querySelector("strong").textContent = tipo.nome;
|
||||||
|
item.querySelector("span").textContent = tipo.descricao;
|
||||||
|
item.querySelector(".video-type-meta").textContent = tipo.duracao_maxima_segundos + " s · " + tipo.proporcao + " · " + tipo.canais;
|
||||||
|
item.querySelector("button").onclick = function () { tipoVideoEditar(tipo.id); };
|
||||||
|
lista.appendChild(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoNovo() {
|
||||||
|
tipoVideoAtualId = null;
|
||||||
|
tipoVideoPreencher(tipoVideoCompletar({ id: "", nome: "", duracao_maxima_segundos: 60, descricao: "", canais: "", proporcao: "9:16", ritmo: "equilibrado", emocao: "", storytelling: true, estrutura: "", cortes: "", broll: "", texto: "", som: "", diretriz: "" }));
|
||||||
|
document.getElementById("tipoVideoEditorTitulo").textContent = "Novo tipo de vídeo";
|
||||||
|
document.getElementById("tipoVideoEditorStatus").textContent = "Rascunho";
|
||||||
|
document.getElementById("tipoVideoEditorCard").hidden = false;
|
||||||
|
tiposVideoRenderizarLista();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoEditar(id) {
|
||||||
|
var tipo = tiposVideoLer().filter(function (item) { return item.id === id; })[0];
|
||||||
|
if (!tipo) return;
|
||||||
|
tipoVideoAtualId = id;
|
||||||
|
tipoVideoPreencher(tipo);
|
||||||
|
document.getElementById("tipoVideoEditorTitulo").textContent = "Editar tipo de vídeo";
|
||||||
|
document.getElementById("tipoVideoEditorStatus").textContent = "Cadastrado";
|
||||||
|
document.getElementById("tipoVideoEditorCard").hidden = false;
|
||||||
|
tiposVideoRenderizarLista();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoPreencher(tipo) {
|
||||||
|
tipo = tipoVideoCompletar(tipo);
|
||||||
|
["nome", "descricao", "canais", "proporcao", "ritmo", "emocao", "estrutura", "cortes", "broll", "texto", "som", "diretriz", "categoria", "objetivo", "objetivo_secundario", "publico", "mensagem", "tipo_narrativa", "foco_narrativo", "tom", "construcao_emocao", "restricoes", "qualidade", "prioridade_voz"].forEach(function (campo) {
|
||||||
|
var elemento = document.getElementById("tipoVideo" + campo.charAt(0).toUpperCase() + campo.slice(1));
|
||||||
|
if (elemento) elemento.value = tipo[campo] || "";
|
||||||
|
});
|
||||||
|
document.getElementById("tipoVideoDuracao").value = tipo.duracao_maxima_segundos || "";
|
||||||
|
document.getElementById("tipoVideoDuracaoMinima").value = tipo.duracao_minima || "";
|
||||||
|
document.getElementById("tipoVideoStorytelling").checked = !!tipo.storytelling;
|
||||||
|
document.getElementById("tipoVideoAtivo").checked = tipo.ativo !== false;
|
||||||
|
document.getElementById("tipoVideoIntensidade").value = tipo.intensidade || 3;
|
||||||
|
document.getElementById("tipoVideoIntensidadeMusica").value = tipo.intensidade_musica || 0;
|
||||||
|
document.getElementById("tipoVideoUsaBroll").checked = !!tipo.usa_broll;
|
||||||
|
document.getElementById("tipoVideoUsaLegendas").checked = !!tipo.usa_legendas;
|
||||||
|
document.getElementById("tipoVideoUsaTextos").checked = !!tipo.usa_textos;
|
||||||
|
document.getElementById("tipoVideoUsaGraficos").checked = !!tipo.usa_graficos;
|
||||||
|
document.getElementById("tipoVideoUsaZoom").checked = !!tipo.usa_zoom;
|
||||||
|
document.getElementById("tipoVideoUsaMusica").checked = !!tipo.usa_musica;
|
||||||
|
tipoVideoRenderizarPrioridades(tipo.prioridades);
|
||||||
|
tipoVideoAtualizarIntensidade();
|
||||||
|
tipoVideoAtualizarIntensidadeMusica();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoRenderizarPrioridades(prioridades) {
|
||||||
|
var lista = document.getElementById("tipoVideoPrioridades");
|
||||||
|
lista.innerHTML = "";
|
||||||
|
(prioridades || []).slice(0, 5).forEach(function (valor, indice) {
|
||||||
|
var linha = document.createElement("div");
|
||||||
|
linha.className = "priority-row";
|
||||||
|
linha.innerHTML = '<span class="priority-number">' + (indice + 1) + '</span><input class="text-field priority-input" type="text" value="">';
|
||||||
|
linha.querySelector("input").value = valor;
|
||||||
|
lista.appendChild(linha);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoPrioridadesDoFormulario() {
|
||||||
|
return Array.prototype.slice.call(document.querySelectorAll("#tipoVideoPrioridades .priority-input")).map(function (input) { return input.value.trim(); }).filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoAtualizarIntensidade() {
|
||||||
|
var valor = document.getElementById("tipoVideoIntensidade");
|
||||||
|
var saida = document.getElementById("tipoVideoIntensidadeValor");
|
||||||
|
if (valor && saida) saida.textContent = valor.value + " / 5";
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoAtualizarIntensidadeMusica() {
|
||||||
|
var valor = document.getElementById("tipoVideoIntensidadeMusica");
|
||||||
|
var saida = document.getElementById("tipoVideoIntensidadeMusicaValor");
|
||||||
|
if (valor && saida) saida.textContent = valor.value + "%";
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoDoFormulario() {
|
||||||
|
var nome = document.getElementById("tipoVideoNome").value.trim();
|
||||||
|
if (!nome) throw new Error("Informe o nome do tipo de vídeo.");
|
||||||
|
var base = tipoVideoAtualId ? tiposVideoLer().filter(function (item) { return item.id === tipoVideoAtualId; })[0] : null;
|
||||||
|
return {
|
||||||
|
id: tipoVideoAtualId || (nome.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") + "-" + Date.now()),
|
||||||
|
nome: nome,
|
||||||
|
descricao: document.getElementById("tipoVideoDescricao").value.trim(),
|
||||||
|
ativo: document.getElementById("tipoVideoAtivo").checked,
|
||||||
|
categoria: document.getElementById("tipoVideoCategoria").value,
|
||||||
|
objetivo: document.getElementById("tipoVideoObjetivo").value.trim(),
|
||||||
|
objetivo_secundario: document.getElementById("tipoVideoObjetivoSecundario").value.trim(),
|
||||||
|
publico: document.getElementById("tipoVideoPublico").value.trim(),
|
||||||
|
mensagem: document.getElementById("tipoVideoMensagem").value.trim(),
|
||||||
|
tipo_narrativa: document.getElementById("tipoVideoTipoNarrativa").value,
|
||||||
|
foco_narrativo: document.getElementById("tipoVideoFocoNarrativo").value.trim(),
|
||||||
|
intensidade: Number(document.getElementById("tipoVideoIntensidade").value) || 3,
|
||||||
|
tom: document.getElementById("tipoVideoTom").value,
|
||||||
|
construcao_emocao: document.getElementById("tipoVideoConstrucaoEmocao").value.trim(),
|
||||||
|
duracao_maxima_segundos: Number(document.getElementById("tipoVideoDuracao").value) || 0,
|
||||||
|
duracao_minima: Number(document.getElementById("tipoVideoDuracaoMinima").value) || 0,
|
||||||
|
canais: document.getElementById("tipoVideoCanais").value.trim(),
|
||||||
|
proporcao: document.getElementById("tipoVideoProporcao").value,
|
||||||
|
ritmo: document.getElementById("tipoVideoRitmo").value,
|
||||||
|
emocao: document.getElementById("tipoVideoEmocao").value.trim(),
|
||||||
|
storytelling: document.getElementById("tipoVideoStorytelling").checked,
|
||||||
|
estrutura: document.getElementById("tipoVideoEstrutura").value.trim(),
|
||||||
|
cortes: document.getElementById("tipoVideoCortes").value.trim(),
|
||||||
|
broll: document.getElementById("tipoVideoBroll").value.trim(),
|
||||||
|
texto: document.getElementById("tipoVideoTexto").value.trim(),
|
||||||
|
som: document.getElementById("tipoVideoSom").value.trim(),
|
||||||
|
diretriz: document.getElementById("tipoVideoDiretriz").value.trim(),
|
||||||
|
prioridades: tipoVideoPrioridadesDoFormulario(),
|
||||||
|
usa_broll: document.getElementById("tipoVideoUsaBroll").checked,
|
||||||
|
usa_legendas: document.getElementById("tipoVideoUsaLegendas").checked,
|
||||||
|
usa_textos: document.getElementById("tipoVideoUsaTextos").checked,
|
||||||
|
usa_graficos: document.getElementById("tipoVideoUsaGraficos").checked,
|
||||||
|
usa_zoom: document.getElementById("tipoVideoUsaZoom").checked,
|
||||||
|
usa_musica: document.getElementById("tipoVideoUsaMusica").checked,
|
||||||
|
intensidade_musica: Number(document.getElementById("tipoVideoIntensidadeMusica").value) || 0,
|
||||||
|
prioridade_voz: document.getElementById("tipoVideoPrioridadeVoz").value,
|
||||||
|
restricoes: document.getElementById("tipoVideoRestricoes").value.trim(),
|
||||||
|
qualidade: document.getElementById("tipoVideoQualidade").value.trim(),
|
||||||
|
criado_em: base && base.criado_em ? base.criado_em : new Date().toISOString(),
|
||||||
|
atualizado_em: new Date().toISOString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoSalvar() {
|
||||||
|
try {
|
||||||
|
var item = tipoVideoDoFormulario();
|
||||||
|
var lista = tiposVideoLer();
|
||||||
|
var indice = lista.findIndex(function (tipo) { return tipo.id === item.id; });
|
||||||
|
if (indice >= 0) lista[indice] = item; else lista.push(item);
|
||||||
|
tiposVideoSalvarNoCatalogo(lista);
|
||||||
|
tipoVideoAtualId = item.id;
|
||||||
|
document.getElementById("tipoVideoEditorStatus").textContent = "Salvo";
|
||||||
|
document.getElementById("tiposVideoStatus").textContent = "Catálogo salvo localmente · " + lista.length + " tipo(s) cadastrado(s).";
|
||||||
|
tiposVideoRenderizarLista();
|
||||||
|
showToast("ok", "Tipo de vídeo salvo no catálogo.");
|
||||||
|
} catch (erro) { showToast("err", erro.message); }
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoCancelar() {
|
||||||
|
tipoVideoAtualId = null;
|
||||||
|
document.getElementById("tipoVideoEditorCard").hidden = true;
|
||||||
|
tiposVideoRenderizarLista();
|
||||||
|
}
|
||||||
|
|
||||||
|
function tipoVideoCopiarJson() {
|
||||||
|
try {
|
||||||
|
var json = JSON.stringify({ tipo_de_video: tipoVideoDoFormulario() }, null, 2);
|
||||||
|
var copia = childProcess.spawn("pbcopy");
|
||||||
|
copia.stdin.end(json);
|
||||||
|
showToast("ok", "Configuração copiada em JSON para a IA.");
|
||||||
|
} catch (erro) { showToast("err", erro.message); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Análises ---------------------------------------------------------------
|
// ---- Análises ---------------------------------------------------------------
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ h1, h2, h3 { margin: 0; }
|
|||||||
padding: 0 14px;
|
padding: 0 14px;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-button {
|
.tab-button {
|
||||||
@@ -139,6 +140,8 @@ h1, h2, h3 { margin: 0; }
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
transition: color .15s, border-color .15s;
|
transition: color .15s, border-color .15s;
|
||||||
}
|
}
|
||||||
|
.tab-bar::-webkit-scrollbar { height: 3px; }
|
||||||
|
.tab-bar::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
|
||||||
.tab-icon { font-size: 11px; opacity: .8; }
|
.tab-icon { font-size: 11px; opacity: .8; }
|
||||||
.tab-button:hover { color: var(--text-secondary); }
|
.tab-button:hover { color: var(--text-secondary); }
|
||||||
.tab-button.active { color: var(--text); border-bottom-color: var(--violet); }
|
.tab-button.active { color: var(--text); border-bottom-color: var(--violet); }
|
||||||
@@ -332,7 +335,7 @@ h1, h2, h3 { margin: 0; }
|
|||||||
.field-static { margin: 0; padding: 8px 0; color: var(--text-secondary); font-size: 10.5px; }
|
.field-static { margin: 0; padding: 8px 0; color: var(--text-secondary); font-size: 10.5px; }
|
||||||
.field-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); gap: 10px; }
|
.field-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, .8fr); gap: 10px; }
|
||||||
|
|
||||||
.select-field, .path-field input, textarea, .file-field input {
|
.select-field, .text-field, .path-field input, textarea, .file-field input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
@@ -342,14 +345,15 @@ h1, h2, h3 { margin: 0; }
|
|||||||
transition: border-color .15s, box-shadow .15s;
|
transition: border-color .15s, box-shadow .15s;
|
||||||
}
|
}
|
||||||
.select-field { height: 32px; padding: 0 8px; font-size: 10.5px; }
|
.select-field { height: 32px; padding: 0 8px; font-size: 10.5px; }
|
||||||
|
.text-field { height: 32px; padding: 0 9px; font-size: 10.5px; outline: none; user-select: text; }
|
||||||
.range-field-row { display: flex; align-items: center; gap: 10px; }
|
.range-field-row { display: flex; align-items: center; gap: 10px; }
|
||||||
.range-field-row input[type="range"] { flex: 1 1 auto; accent-color: var(--violet); height: 20px; }
|
.range-field-row input[type="range"] { flex: 1 1 auto; accent-color: var(--violet); height: 20px; }
|
||||||
.range-field-value { flex: 0 0 auto; min-width: 84px; text-align: right; font: 10.5px var(--font-mono); color: var(--text-secondary); }
|
.range-field-value { flex: 0 0 auto; min-width: 84px; text-align: right; font: 10.5px var(--font-mono); color: var(--text-secondary); }
|
||||||
.path-field input, .file-field input { height: 34px; padding: 0 10px; font: 10px var(--font-mono); color: var(--text-secondary); user-select: text; }
|
.path-field input, .file-field input { height: 34px; padding: 0 10px; font: 10px var(--font-mono); color: var(--text-secondary); user-select: text; }
|
||||||
.path-field > svg + input { padding-left: 32px; }
|
.path-field > svg + input { padding-left: 32px; }
|
||||||
textarea { padding: 8px 10px; font: 10px var(--font-mono); color: var(--text-secondary); resize: vertical; user-select: text; }
|
textarea { padding: 8px 10px; font: 10px var(--font-mono); color: var(--text-secondary); resize: vertical; user-select: text; }
|
||||||
.select-field:hover, .path-field input:hover, textarea:hover, .file-field input:hover { border-color: var(--border-strong); }
|
.select-field:hover, .text-field:hover, .path-field input:hover, textarea:hover, .file-field input:hover { border-color: var(--border-strong); }
|
||||||
.select-field:focus, .path-field input:focus, textarea:focus, .file-field input:focus { border-color: var(--violet); color: var(--text); box-shadow: 0 0 0 2px var(--violet-soft); }
|
.select-field:focus, .text-field:focus, .path-field input:focus, textarea:focus, .file-field input:focus { border-color: var(--violet); color: var(--text); box-shadow: 0 0 0 2px var(--violet-soft); }
|
||||||
|
|
||||||
.path-field { position: relative; display: flex; align-items: center; }
|
.path-field { position: relative; display: flex; align-items: center; }
|
||||||
.path-field > svg { position: absolute; left: 10px; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; color: var(--text-muted); pointer-events: none; }
|
.path-field > svg { position: absolute; left: 10px; width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.5; color: var(--text-muted); pointer-events: none; }
|
||||||
@@ -381,6 +385,31 @@ textarea { padding: 8px 10px; font: 10px var(--font-mono); color: var(--text-sec
|
|||||||
.button-row { display: flex; gap: 8px; }
|
.button-row { display: flex; gap: 8px; }
|
||||||
.button-row .button { flex: 1; }
|
.button-row .button { flex: 1; }
|
||||||
|
|
||||||
|
/* -------------------------- Catálogo editorial ------------------------- */
|
||||||
|
.video-type-list { display: grid; gap: 6px; }
|
||||||
|
.video-type-row { display: flex; align-items: center; gap: 9px; padding: 9px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-deep); }
|
||||||
|
.video-type-row.is-selected { border-color: rgba(155, 108, 255, .55); background: var(--violet-soft); }
|
||||||
|
.video-type-copy { flex: 1; min-width: 0; }
|
||||||
|
.video-type-copy strong, .video-type-copy span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.video-type-copy strong { color: var(--text); font-size: 10.5px; font-weight: 650; }
|
||||||
|
.video-type-copy span { margin-top: 3px; color: var(--text-muted); font-size: 9px; }
|
||||||
|
.video-type-meta { max-width: 32%; overflow: hidden; color: var(--text-muted); font: 8.5px var(--font-mono); text-overflow: ellipsis; white-space: nowrap; }
|
||||||
|
.video-type-row .button { height: 27px; padding: 0 9px; flex: 0 0 auto; font-size: 9px; }
|
||||||
|
.profile-section { margin-top: 12px; padding: 12px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface-deep); }
|
||||||
|
.profile-section-head { display: flex; align-items: center; gap: 9px; margin-bottom: 11px; }
|
||||||
|
.profile-section-head > span { display: flex; align-items: center; justify-content: center; width: 22px; height: 22px; flex: 0 0 auto; border-radius: 50%; background: var(--violet-soft); color: var(--violet-hover); font-size: 10px; font-weight: 700; }
|
||||||
|
.profile-section-head strong, .profile-section-head small { display: block; }
|
||||||
|
.profile-section-head strong { font-size: 10.5px; font-weight: 650; }
|
||||||
|
.profile-section-head small { margin-top: 2px; color: var(--text-muted); font-size: 9px; }
|
||||||
|
.profile-section > * + * { margin-top: 9px; }
|
||||||
|
.profile-section .checkbox-field { margin-top: 9px; }
|
||||||
|
.profile-section output { float: right; color: var(--text-muted); font: 9px var(--font-mono); }
|
||||||
|
.profile-section input[type="range"] { width: 100%; accent-color: var(--violet); }
|
||||||
|
.priority-list { display: grid; gap: 6px; }
|
||||||
|
.priority-row { display: flex; align-items: center; gap: 7px; }
|
||||||
|
.priority-number { display: flex; align-items: center; justify-content: center; width: 20px; height: 20px; flex: 0 0 auto; border-radius: 50%; background: var(--surface-raised); color: var(--text-muted); font: 9px var(--font-mono); }
|
||||||
|
.priority-input { flex: 1; }
|
||||||
|
|
||||||
/* ---------------------------- Chave/valor, stats ---------------------------- */
|
/* ---------------------------- Chave/valor, stats ---------------------------- */
|
||||||
.kv { display: grid; gap: 1px; margin: 0; padding: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 6px; background: var(--border); }
|
.kv { display: grid; gap: 1px; margin: 0; padding: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 6px; background: var(--border); }
|
||||||
.kv[hidden] { display: none; }
|
.kv[hidden] { display: none; }
|
||||||
|
|||||||
@@ -0,0 +1,100 @@
|
|||||||
|
{
|
||||||
|
"schema_version": "1.0",
|
||||||
|
"tipo": "plano_de_resumo_jornalistico",
|
||||||
|
"objetivo": "Resumir a entrevista sobre a crise no STF, seus efeitos institucionais e possíveis impactos eleitorais.",
|
||||||
|
"duracao_maxima_segundos": 180,
|
||||||
|
"duracao_estimada_segundos": 176.43,
|
||||||
|
"fonte": {
|
||||||
|
"arquivo": "videoplayback (1).mp4",
|
||||||
|
"caminho": "/Volumes/Merongo/Downloads/videoplayback (1).mp4"
|
||||||
|
},
|
||||||
|
"regras": {
|
||||||
|
"excluir_falantes": ["SPEAKER_01"],
|
||||||
|
"manter_falantes": ["SPEAKER_00", "SPEAKER_02", "SPEAKER_03"],
|
||||||
|
"remover_silencios_excessivos": true,
|
||||||
|
"preservar_sentido_original": true,
|
||||||
|
"adicionar_legendas": true
|
||||||
|
},
|
||||||
|
"estrutura": [
|
||||||
|
{
|
||||||
|
"ordem": 1,
|
||||||
|
"segmento_origem": 9,
|
||||||
|
"falante": "Fabiola",
|
||||||
|
"speaker_id": "SPEAKER_00",
|
||||||
|
"entrada": "00:03:08.780",
|
||||||
|
"saida": "00:03:30.800",
|
||||||
|
"duracao_segundos": 22.02,
|
||||||
|
"funcao": "abertura_e_contexto",
|
||||||
|
"justificativa": "Apresenta a crise como uma tragédia e introduz a análise do professor Marco Teixeira."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordem": 2,
|
||||||
|
"segmentos_origem": [10, 11, 12],
|
||||||
|
"falante": "Marco Teixeira",
|
||||||
|
"speaker_id": "SPEAKER_02",
|
||||||
|
"entrada": "00:03:31.750",
|
||||||
|
"saida": "00:04:20.020",
|
||||||
|
"duracao_segundos": 48.27,
|
||||||
|
"funcao": "diagnostico_institucional",
|
||||||
|
"justificativa": "Explica que a crise mina a confiança no Judiciário, envolve os demais Poderes e foi agravada pela demora na reação."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordem": 3,
|
||||||
|
"segmento_origem": 18,
|
||||||
|
"falante": "Marco Teixeira",
|
||||||
|
"speaker_id": "SPEAKER_02",
|
||||||
|
"entrada": "00:06:39.910",
|
||||||
|
"saida": "00:07:19.900",
|
||||||
|
"duracao_segundos": 39.99,
|
||||||
|
"funcao": "impacto_politico",
|
||||||
|
"justificativa": "Mostra que as decisões possuem impacto eleitoral e podem provocar uma crise dentro do STF e da Polícia Federal."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordem": 4,
|
||||||
|
"segmento_origem": 20,
|
||||||
|
"falante": "Marco Teixeira",
|
||||||
|
"speaker_id": "SPEAKER_02",
|
||||||
|
"entrada": "00:07:42.140",
|
||||||
|
"saida": "00:08:10.050",
|
||||||
|
"duracao_segundos": 27.91,
|
||||||
|
"funcao": "conclusao_do_analista",
|
||||||
|
"justificativa": "Defende previsibilidade, respeito às instituições e alerta para o risco de enfraquecimento dos Poderes."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordem": 5,
|
||||||
|
"segmento_origem": 23,
|
||||||
|
"falante": "Outro",
|
||||||
|
"speaker_id": "SPEAKER_03",
|
||||||
|
"entrada": "00:09:27.980",
|
||||||
|
"saida": "00:09:37.260",
|
||||||
|
"duracao_segundos": 9.28,
|
||||||
|
"funcao": "transicao_e_metafora",
|
||||||
|
"justificativa": "Introduz uma metáfora forte para explicar a escalada do conflito no Supremo."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ordem": 6,
|
||||||
|
"segmento_origem": 25,
|
||||||
|
"falante": "Outro",
|
||||||
|
"speaker_id": "SPEAKER_03",
|
||||||
|
"entrada": "00:09:38.110",
|
||||||
|
"saida": "00:10:07.070",
|
||||||
|
"duracao_segundos": 28.96,
|
||||||
|
"funcao": "fechamento_de_impacto",
|
||||||
|
"justificativa": "Resume a crise como uma disputa interna grave e reforça o conflito entre decisões individuais e o funcionamento colegiado do STF."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"orientacoes_de_edicao": {
|
||||||
|
"ritmo": "informativo, firme e crescente",
|
||||||
|
"abertura": "Começar diretamente com a pergunta de Fabiola, sem vinheta longa.",
|
||||||
|
"cortes": "Remover cumprimentos, repetições, hesitações e pausas prolongadas.",
|
||||||
|
"transicoes": "Usar cortes secos entre os blocos, com transições discretas.",
|
||||||
|
"legendas": "Aplicar legendas sincronizadas e destacar termos como STF, democracia, eleições e instituições.",
|
||||||
|
"texto_na_tela": [
|
||||||
|
"Crise institucional no STF",
|
||||||
|
"Impactos sobre a democracia e as eleições",
|
||||||
|
"O risco de enfraquecimento das instituições"
|
||||||
|
],
|
||||||
|
"trilha": "Opcional, discreta e de tensão jornalística, sem encobrir as falas.",
|
||||||
|
"checagem": "Conferir no áudio os nomes Fachin, Andrei Rodrigues e demais termos corrigidos da transcrição."
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user