图片渲染
约 706 字大约 2 分钟
2026-09-15
渲染管线是「模板 + 数据 → 图片」,模板放插件自己的 resources/ 下,语法是 art-template。
模板约定
plugins/my-plugin/resources/help/index.html<div id="container">
<h1>{{ title }}</h1>
<img src="{{ pluResPath }}img/logo.png" />
<ul>
{{ each list item }}
<li>{{ item.name }} — {{ item.value }}</li>
{{ /each }}
</ul>
</div>模板里可用的约定变量:
| 变量 | 说明 |
|---|---|
pluResPath | 插件资源目录,已在 resources/ 级别,直接拼相对路径 |
_res_path | 同上(云崽旧写法) |
sys | 渲染时注入的公共信息 |
调用方式
原生类形态(推荐):
const img = await this.render('help/index', { title: '标题' })
await e.reply(img || '渲染失败')
const b64 = await this.renderBase64('help/index', data) // 需要 base64:// 时
await e.reply([segment.image(b64)])通用 / DSL:
// 直接发送(返回 true 或消息 id)
await e.runtime.render('my-plugin', 'help/index', data)
// 只要 base64 字符串
const base64 = await e.runtime.render('my-plugin', 'help/index', data, { retType: 'base64' })旧写法(与云崽一致,迁移插件不用改):
import puppeteer from '../../lib/puppeteer/puppeteer.js'
const img = await puppeteer.screenshot('my-plugin/help/index', {
tplFile: './plugins/my-plugin/resources/help/index.html',
saveId: 'index',
pluResPath: './plugins/my-plugin/resources/',
...data,
})
await e.reply(img)长图分页
超过指定高度会自动切片,返回多张图片段:
const imgs = await puppeteer.screenshots('my-plugin/long/index', {
tplFile: './plugins/my-plugin/resources/long/index.html',
saveId: 'index',
pluResPath: '../../../plugins/my-plugin/resources/',
pageHeight: 4000,
...data,
})
for (const img of imgs) await e.reply(img)可直接运行的例子:plugins/demo/render-demo.js(#渲染测试 #渲染列表 #渲染图片 #渲染长图 #渲染状态)。
渲染后端
内置 puppeteer 后端,用本机 Chrome / Edge。配置在 renderers/puppeteer/config.yaml:
chromiumPath: # 浏览器路径,留空自动查找
headless: "new"
args: [--disable-gpu, --no-sandbox, ...]
puppeteerTimeout: # 截图超时
pageGotoParams:
timeout: 120000
restartNum: 100 # 截图 N 张后重启浏览器,避免越截越慢
idleTime: 30 # 空闲 N 分钟后关闭浏览器,下次截图自动启动
userDataDir: # 用户数据目录浏览器是懒启动的:第一次截图才拉起,空闲后自动关闭。日志会记录程序路径、参数、数据目录、 截图张数与耗时。
自定义渲染后端
新建 renderers/<id>/index.js:
export default function (config) {
return {
id: 'my-renderer',
type: 'image',
support_script: true,
async render(name, data) {
// 返回 Buffer / Buffer[] / base64 字符串;返回 false 表示交给下一个后端
},
}
}也可以用 config/config/renderer.yaml → name 显式指定用哪个后端(留空为自动选择)。
排查渲染问题
#渲染测试— 基础卡片能不能出图(plugins/demo/)#渲染状态— 后端是否加载、Chromium 是否在跑、本次已出图张数、耗时排行#诊断— 渲染自检- 日志过滤
[ Render ],失败时会打印模板路径、行列号与报错 - 没有浏览器时框架会自动装(Linux 上优先用包管理器,并装上中文字体与 emoji 字体);也可用
renderers/puppeteer/config.yaml → chromiumPath指定 - 图里中文/emoji 显示成方块 = 系统缺字体(
fonts-noto-cjk/fonts-noto-color-emoji),框架会在启动浏览器时自检并提醒 - 自检:
#渲染测试/#渲染状态/#诊断,详见常见问题
