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:
@ -33,6 +33,7 @@ export default async function handler(req, res) {
|
||||
likes = null,
|
||||
compartidos = null,
|
||||
fecha_publicacion = null,
|
||||
contexto_video = '',
|
||||
} = req.body
|
||||
|
||||
if (!url) return res.status(400).json({ error: 'El campo "url" es requerido' })
|
||||
@ -56,7 +57,7 @@ export default async function handler(req, res) {
|
||||
|
||||
// ── PASO 3: Analizar con GPT-4o ───────────────────────
|
||||
paso = 'analisis'
|
||||
const analisisRaw = await analizarTranscript(transcript, niche, plataforma, duracion)
|
||||
const analisisRaw = await analizarTranscript(transcript, niche, plataforma, duracion, contexto_video)
|
||||
|
||||
// ── PASO 4: Validar con Zod ───────────────────────────
|
||||
paso = 'validacion'
|
||||
@ -136,6 +137,13 @@ export default async function handler(req, res) {
|
||||
persona_narradora: analisis.persona_narradora,
|
||||
promesa_explicita: analisis.promesa_explicita,
|
||||
nivel_especificidad: analisis.nivel_especificidad,
|
||||
contexto_video: contexto_video || null,
|
||||
|
||||
// Diagnóstico
|
||||
fortalezas: analisis.fortalezas,
|
||||
debilidades: analisis.debilidades,
|
||||
sugerencias_mejora: analisis.sugerencias_mejora,
|
||||
hashtags_sugeridos: analisis.hashtags_sugeridos,
|
||||
|
||||
// Métricas (score_engagement lo calcula el trigger de Supabase)
|
||||
score_virabilidad: analisis.score_virabilidad,
|
||||
|
||||
@ -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>"
|
||||
}`
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -111,6 +111,7 @@ app.post('/api/analizar', async (req, res) => {
|
||||
competidor_referente = false,
|
||||
vistas = null, likes = null, compartidos = null,
|
||||
fecha_publicacion = null,
|
||||
contexto_video = '',
|
||||
} = req.body
|
||||
|
||||
if (!url) return res.status(400).json({ error: 'El campo "url" es requerido' })
|
||||
@ -135,7 +136,7 @@ app.post('/api/analizar', async (req, res) => {
|
||||
|
||||
paso = 'analisis'
|
||||
console.log(`[3/5] Analizando con GPT-4o...`)
|
||||
const analisisRaw = await analizarTranscript(transcript, niche, plataforma, duracion)
|
||||
const analisisRaw = await analizarTranscript(transcript, niche, plataforma, duracion, contexto_video)
|
||||
|
||||
paso = 'validacion'
|
||||
console.log(`[4/5] Validando schema...`)
|
||||
@ -152,6 +153,7 @@ app.post('/api/analizar', async (req, res) => {
|
||||
proyecto_nombre, competidor_referente,
|
||||
url_origen: url, plataforma, duracion_segundos: duracion,
|
||||
vistas, likes, compartidos, fecha_publicacion,
|
||||
contexto_video: contexto_video || null,
|
||||
...analisis,
|
||||
transcript,
|
||||
embedding_vector: `[${vector.join(',')}]`,
|
||||
|
||||
Reference in New Issue
Block a user