novel-to-script
v1.0.0
Published
将网文小说文本转换为电影解说风格的结构化剧本 JSON
Readme
novel-to-script
将网文小说文本转换为"电影解说风格"的结构化剧本 JSON,供有声书合成流水线使用。
安装
npm install novel-to-script使用
流式输出(推荐)
import { generateScriptStream } from "novel-to-script";
const stream = generateScriptStream(novelText, {
systemPrompt: "你是一位专业的有声书剧本编剧...", // 必传,自定义 LLM 提示词
style: "悬疑",
llmConfig: {
apiKey: "sk-...",
baseURL: "https://api.deepseek.com/v1",
model: "deepseek-chat",
thinking: true,
},
});
for await (const event of stream) {
switch (event.type) {
case "thinking": console.log("[思考]", event.text); break;
case "chunk": process.stdout.write(event.text); break;
case "node": console.log("[节点]", event.node); break;
case "progress": console.log(`进度: ${event.current}/${event.total}`); break;
case "done": console.log("完成", event.usage); break;
case "error": console.error(event.error); break;
}
}非流式(便捷)
import { generateScript } from "novel-to-script";
const result = await generateScript(novelText, {
systemPrompt: "你是一位专业的有声书剧本编剧...",
llmConfig: { apiKey: "sk-...", model: "qwen-plus" },
});
result.nodes; // ScriptNode[]
result.usage; // { promptTokens, completionTokens, totalTokens }角色档案提取
import { extractCharacters } from "novel-to-script";
const { characters, usage } = await extractCharacters(
result.nodes,
novelText,
{ apiKey: "sk-...", model: "qwen-plus" }
);
// characters: CharacterProfile[]
// { name, gender, age, voiceTraits, role }配置项
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| systemPrompt | string | - | 必传,LLM 系统提示词 |
| style | string | "标准" | 解说风格:悬疑、轻松、深情等 |
| preserveDialogue | boolean | true | 是否保留原对话 |
| extraPrompt | string | - | 额外追加给 LLM 的自定义指令 |
| llmConfig | LLMConfig | - | LLM 配置(useFallback=true 时可不传) |
| maxNodes | number | - | 最大输出节点数 |
| maxRetries | number | 3 | 最大重试次数 |
| useFallback | boolean | false | 强制使用规则回退解析器 |
| fallbackOnError | boolean | true | LLM 失败时自动回退 |
| maxTokensPerChunk | number | 2000 | 每段最大 token 数 |
| signal | AbortSignal | - | 取消控制 |
| onLog | function | - | 日志回调 |
LLMConfig
| 参数 | 说明 |
|------|------|
| apiKey | API 密钥(必填) |
| baseURL | API 地址(默认 OpenAI,可切换 DeepSeek/通义千问等) |
| model | 模型名称,默认 gpt-4o |
| timeout | 请求超时 ms,默认 60000 |
| thinking | 启用思考模式,默认 false |
输出结构
// 旁白
{ type: "narration", speaker: "主讲人", text: "...", emotion: "紧张" }
// 对白
{ type: "dialogue", speaker: "陈默", text: "谁?", emotion: "警觉" }
// 环境音效
{ type: "ambience", description: "大雨倾盆,雷声轰鸣", duration: 5 }CharacterProfile
{
name: string; // 角色名
gender: "male" | "female" | "unknown";
age: "child" | "young" | "middle" | "old" | "unknown";
voiceTraits: string; // 声音特点,如"低沉浑厚,略带沙哑"
role: "protagonist" | "supporting" | "minor";
}错误处理
import { LLMConnectionError, TokenLimitError, ParseError, ConfigError } from "novel-to-script";
try {
const result = await generateScript(text, options);
} catch (err) {
if (err instanceof TokenLimitError) { /* 文本太长 */ }
if (err instanceof LLMConnectionError) { /* 网络问题 */ }
if (err instanceof ConfigError) { /* 缺少 systemPrompt 或 llmConfig */ }
}回退解析器
import { fallbackParse } from "novel-to-script";
const nodes = fallbackParse(text); // 无需 LLM,纯正则Playground
开发测试前端位于 playground/ 目录:
# 启动后端
cd playground/server && npm install && npm run dev
# 启动前端(新终端)
cd playground/client && npm install && npm run dev访问 http://localhost:5173 配置 LLM 信息后测试。
