diff --git a/code/cep-plugin/index.html b/code/cep-plugin/index.html index e212506..49c6f6e 100755 --- a/code/cep-plugin/index.html +++ b/code/cep-plugin/index.html @@ -34,6 +34,9 @@ + @@ -374,6 +377,76 @@ + + + diff --git a/code/cep-plugin/main.js b/code/cep-plugin/main.js index cfbbf30..fdde7d9 100755 --- a/code/cep-plugin/main.js +++ b/code/cep-plugin/main.js @@ -30,6 +30,28 @@ function log(msg, cls) { // 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 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 formatClock(ms) { @@ -207,6 +229,7 @@ function switchTab(name) { { key: "scanner", panel: "tabScanner", btn: "tabBtnScanner" }, { key: "retakes", panel: "tabRetakes", btn: "tabBtnRetakes" }, { key: "analises", panel: "tabAnalises", btn: "tabBtnAnalises" }, + { key: "tipos-video", panel: "tabTiposVideo", btn: "tabBtnTiposVideo" }, { key: "bridge", panel: "tabBridge", btn: "tabBtnBridge" }, { key: "models", panel: "tabModels", btn: "tabBtnModels" }, { key: "settings", panel: "tabSettings", btn: "tabBtnSettings" }, @@ -226,6 +249,196 @@ function switchTab(name) { if (name === "scanner") { renderScannerTranscriptionOptions(); loadScannerProfile(); renderScannerHuggingFaceStatus(); } if (name === "retakes") retakesAoAbrir(); 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 = '
'; + 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 = '' + (indice + 1) + ''; + 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 --------------------------------------------------------------- diff --git a/code/cep-plugin/styles.css b/code/cep-plugin/styles.css index 9efad95..44f7234 100755 --- a/code/cep-plugin/styles.css +++ b/code/cep-plugin/styles.css @@ -119,6 +119,7 @@ h1, h2, h3 { margin: 0; } padding: 0 14px; border-bottom: 1px solid var(--border); background: var(--bg); + overflow-x: auto; } .tab-button { @@ -139,6 +140,8 @@ h1, h2, h3 { margin: 0; } white-space: nowrap; 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-button:hover { color: var(--text-secondary); } .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-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%; border: 1px solid var(--border); border-radius: 6px; @@ -342,14 +345,15 @@ h1, h2, h3 { margin: 0; } transition: border-color .15s, box-shadow .15s; } .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 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); } .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; } 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: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:hover, .text-field:hover, .path-field input:hover, textarea:hover, .file-field input:hover { border-color: var(--border-strong); } +.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 > 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 .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 ---------------------------- */ .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; } diff --git a/plano-resumo-video.json b/plano-resumo-video.json new file mode 100644 index 0000000..cf75ec3 --- /dev/null +++ b/plano-resumo-video.json @@ -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." + } +}