流式生成
通过流式传输实时监控图像生成进度。支持两种流式格式:
- SSE (Server-Sent Events): 文本格式,默认选项,兼容性好
- msgpack: 二进制格式,更高效,适合高性能场景
基本用法
typescript
import { NovelAI } from 'novelai-sdk-unofficial';
import { writeFileSync } from 'fs';
const client = new NovelAI({ apiKey: 'your-api-key' });
const stream = client.image.generateStream({
prompt: '1girl, detailed background',
model: 'nai-diffusion-4-5-full',
steps: 28,
});
for await (const chunk of stream) {
if (chunk.event_type === 'intermediate') {
console.log(`步骤 ${chunk.step_ix}/${chunk.steps}: sigma=${chunk.sigma}`);
// 可选:保存中间图像
const preview = Buffer.from(chunk.image, 'base64');
writeFileSync(`preview_${chunk.step_ix}.png`, preview);
} else if (chunk.event_type === 'final') {
console.log('生成完成!');
const finalImage = Buffer.from(chunk.image, 'base64');
writeFileSync('final.png', finalImage);
}
}流式格式选择
SSE 格式(默认)
typescript
const stream = client.image.generateStream({
prompt: '1girl',
stream: 'sse', // 默认值,可省略
});msgpack 格式
msgpack 是二进制格式,传输效率更高:
typescript
const stream = client.image.generateStream({
prompt: '1girl',
stream: 'msgpack', // 使用 msgpack 格式
});
for await (const chunk of stream) {
// 使用方式与 SSE 完全相同
if (chunk.event_type === 'final') {
const image = Buffer.from(chunk.image, 'base64');
}
}选择建议:
- 一般场景使用 SSE(默认),调试方便
- 高性能/低延迟场景使用 msgpack
数据块类型
中间数据块
生成过程中接收:
typescript
{
event_type: 'intermediate',
step_ix: number, // 当前步骤(从 0 开始)
steps: number, // 总步数
sigma: number, // 当前 sigma 值
image: string, // Base64 编码的预览图像
}最终数据块
生成完成时接收:
typescript
{
event_type: 'final',
image: string, // Base64 编码的最终图像
}进度显示
typescript
const stream = client.image.generateStream({
prompt: '1girl',
steps: 28,
});
for await (const chunk of stream) {
if (chunk.event_type === 'intermediate') {
const progress = ((chunk.step_ix + 1) / chunk.steps * 100).toFixed(1);
console.log(`进度: ${progress}%`);
}
}带所有参数
流式生成支持所有标准生成参数:
typescript
const stream = client.image.generateStream({
prompt: '1girl, cat ears',
model: 'nai-diffusion-4-5-full',
size: 'portrait',
steps: 28,
scale: 5.0,
sampler: 'k_euler_ancestral',
seed: 12345,
// 高级功能也支持
characterReferences: [...],
controlnet: {...},
i2i: {...},
});错误处理
typescript
try {
const stream = client.image.generateStream({
prompt: '1girl',
});
for await (const chunk of stream) {
// 处理数据块...
}
} catch (error) {
if (error instanceof NetworkError) {
console.error('流式传输过程中连接丢失');
} else {
console.error('生成失败:', error.message);
}
}使用场景
进度条 UI
typescript
async function generateWithProgress(prompt: string) {
const stream = client.image.generateStream({ prompt, steps: 28 });
for await (const chunk of stream) {
if (chunk.event_type === 'intermediate') {
updateProgressBar(chunk.step_ix + 1, chunk.steps);
} else if (chunk.event_type === 'final') {
return Buffer.from(chunk.image, 'base64');
}
}
}实时预览
typescript
async function generateWithPreview(prompt: string, onPreview: (img: Buffer) => void) {
const stream = client.image.generateStream({ prompt });
for await (const chunk of stream) {
if (chunk.event_type === 'intermediate') {
const preview = Buffer.from(chunk.image, 'base64');
onPreview(preview);
} else if (chunk.event_type === 'final') {
return Buffer.from(chunk.image, 'base64');
}
}
}
// 使用
await generateWithPreview('1girl', (preview) => {
// 用预览图像更新 UI
displayImage(preview);
});取消
使用 AbortController 显式取消流式生成:
typescript
const controller = new AbortController();
const stream = client.image.generateStream(
{ prompt: '1girl' },
controller.signal, // 传入 signal
);
// 5 秒后取消
setTimeout(() => controller.abort(), 5000);
try {
for await (const chunk of stream) {
if (chunk.event_type === 'intermediate') {
console.log(`步骤 ${chunk.step_ix}/${chunk.steps}`);
} else if (chunk.event_type === 'final') {
console.log('生成完成');
}
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('生成已取消');
} else {
throw error;
}
}取消会:
- 立即停止接收数据
- 释放网络连接
- 抛出
AbortError异常
## 提示
1. **中间图像质量较低** - 它们用于预览,不是最终用途。
2. **更多步数 = 更多数据块** - 更高的步数会产生更多的中间更新。
3. **网络考虑** - 流式传输需要在整个生成过程中保持稳定连接。
4. **内存使用** - 如果保存所有中间图像,请注意内存/磁盘使用。