zhizhi/modules/drama/server.js

122 lines
4.0 KiB
JavaScript
Raw Normal View History

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}`);
});