feat: contexto de video, análisis extendido y métricas sociales

- Campo "Contexto del Video" en formulario de análisis (Paso 03)
  → se pasa a GPT-4o para enriquecer el análisis
- 4 nuevos campos de diagnóstico: fortalezas, debilidades,
  sugerencias_mejora, hashtags_sugeridos (click para copiar)
- Vista de detalle: card de métricas sociales (vistas/likes/compartidos
  con engagement rate calculado)
- Muestra contexto original ingresado por el usuario
- Migración SQL 07: 5 nuevas columnas en tabla guiones
- validador.js: 4 nuevos campos en schema Zod
- server.js + api/analizar.js: acepta y guarda contexto_video

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-29 21:44:24 -05:00
parent 2fc4168301
commit be69c0aa48
7 changed files with 173 additions and 11 deletions

View File

@ -1,7 +1,7 @@
// ============================================================
// ANALIZADOR — GPT-4o
// Prompt maestro multidisciplinario: Storytelling + Cialdini
// + Neuropublicidad + Copywriting → JSON de 45 campos
// + Neuropublicidad + Copywriting → JSON de 49 campos
// ============================================================
import OpenAI from 'openai'
@ -22,12 +22,17 @@ SOLO devuelve el JSON, sin texto adicional, sin markdown, sin explicaciones.`
* @param {string} niche Nicho del video (ej: "fitness", "finanzas")
* @param {string} plataforma tiktok | reels | shorts
* @param {number} duracion Duración en segundos
* @param {string} contextoVideo Contexto adicional opcional sobre el video
* @returns {object} JSON con todos los campos de análisis
*/
export async function analizarTranscript(transcript, niche, plataforma, duracion) {
export async function analizarTranscript(transcript, niche, plataforma, duracion, contextoVideo = '') {
const bloqueContexto = contextoVideo
? `CONTEXTO ADICIONAL DEL VIDEO (úsalo para enriquecer el análisis):\n"""\n${contextoVideo}\n"""\n\n`
: ''
const promptUsuario = `Analiza este video de ${plataforma} de ${duracion} segundos del nicho "${niche}".
TRANSCRIPCIÓN:
${bloqueContexto}TRANSCRIPCIÓN:
"""
${transcript}
"""
@ -88,6 +93,11 @@ Devuelve EXACTAMENTE este JSON con los valores que correspondan:
"ingredientes_clave": ["<elemento 1 que NO puede faltar si se replica este guion>", "<elemento 2>", "<elemento 3>"],
"replicabilidad": "<alta|media|baja>",
"fortalezas": ["<fortaleza 1 del video: qué hace especialmente bien>", "<fortaleza 2>", "<fortaleza 3>"],
"debilidades": ["<debilidad o área de mejora 1>", "<debilidad 2>"],
"sugerencias_mejora": ["<sugerencia accionable concreta 1 para mejorar el video>", "<sugerencia 2>", "<sugerencia 3>"],
"hashtags_sugeridos": ["<hashtag1>", "<hashtag2>", "<hashtag3>", "<hashtag4>", "<hashtag5>", "<hashtag6>", "<hashtag7>"],
"score_virabilidad": <número entero del 1 al 100>,
"resumen_patron": "<párrafo de 3-4 oraciones describiendo el patrón ganador de este video: qué hace, por qué funciona psicológicamente y cómo se puede replicar>"
}`

View File

@ -81,6 +81,12 @@ export const AnalisisSchema = z.object({
ingredientes_clave: z.array(z.string()).min(1).max(7),
replicabilidad: ReplicabilidadEnum,
// Diagnóstico y mejora
fortalezas: z.array(z.string()).min(1).max(5),
debilidades: z.array(z.string()).min(1).max(5),
sugerencias_mejora: z.array(z.string()).min(1).max(5),
hashtags_sugeridos: z.array(z.string()).min(1).max(10),
// Métricas
score_virabilidad: z.number().int().min(1).max(100),
resumen_patron: z.string().min(10).max(1500),