const http = require('http'); const fs = require('fs'); const path = require('path'); const PORT = 3930; const DEEPSEEK_KEY = 'sk-a9b69e9cd2dc4ca68d6aceaa84f22afb'; // Prompt 模板:三种模式 function buildPrompt(mode, input) { const base = `你是一位专业的真人短剧编剧。请用以下专业格式输出剧本: 【人物表】 列出主要角色及简介 第X幕 场景 X · 地点 · 时间 · 内外景 [镜头提示] 动作/场景描述 角色名:(语气)"对白" 角色名:动作描述 [镜头切至] 下一个镜头 注意: - 每场标注镜头语言(中景、特写、远景、跟拍等) - 对白自然,符合人物性格 - 动作描写简洁有力 - 节奏紧凑,3-5分钟短剧体量`; switch (mode) { case 'auto': return `${base}\n\n用户提供的主题:「${input}」\n请根据这个主题创作一个完整的真人短剧剧本。`; case 'assist': return `${base}\n\n用户提供的想法:「${input}」\n请根据这个想法展开,创作一个完整的真人短剧剧本。`; case 'polish': return `${base}\n\n以下是用户提供的剧本草稿。请在不改变核心情节的前提下,优化对白、增强画面感、调整节奏:\n\n${input}`; default: return `${base}\n\n用户输入:「${input}」`; } } // 简易 HTML 注入 function serveStatic(res, filePath) { const fullPath = path.join(__dirname, 'public', filePath); try { const data = fs.readFileSync(fullPath, 'utf-8'); const ext = path.extname(filePath); const mime = { '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript' }[ext] || 'text/plain'; res.writeHead(200, { 'Content-Type': mime }); res.end(data); } catch { res.writeHead(404); res.end('Not found'); } } const server = http.createServer(async (req, res) => { const url = new URL(req.url, `http://localhost:${PORT}`); const pathname = url.pathname; // CORS res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; } // 静态文件 if (pathname === '/' || pathname === '/index.html') return serveStatic(res, 'index.html'); // 生成剧本 API if (pathname === '/api/generate' && req.method === 'POST') { let body = ''; req.on('data', c => body += c); req.on('end', async () => { try { const { mode, input } = JSON.parse(body); if (!input || input.trim().length < 2) { res.writeHead(400, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: '输入内容至少 2 个字符' })); return; } const prompt = buildPrompt(mode || 'auto', input); // 调 DeepSeek API const apiRes = await fetch('https://api.deepseek.com/chat/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${DEEPSEEK_KEY}` }, body: JSON.stringify({ model: 'deepseek-chat', messages: [ { role: 'system', content: '你是一位专业的真人短剧编剧。输出格式严格遵循用户要求的剧本格式。' }, { role: 'user', content: prompt } ], temperature: 0.8, max_tokens: 4096 }) }); const data = await apiRes.json(); const content = data.choices?.[0]?.message?.content || '生成失败,请重试'; res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true, content })); } catch (e) { res.writeHead(500, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ error: e.message })); } }); return; } res.writeHead(404); res.end('Not found'); }); server.listen(PORT, '0.0.0.0', () => { console.log(`[drama] 启动成功 http://0.0.0.0:${PORT}`); });