图片大模型实践:可灵(Kling)文生图前后端实现

图片大模型实践:可灵(Kling)文生图前后端实现

本文讲图片模型 里「可灵文生图」这一条链路:鉴权、代理、前端如何拼 URL 、如何从异步任务结果里取出最终图片地址。语音或其它模型后续再单独开章节。

建议阅读顺序 :先看下面「快速跑通」与「架构与数据流」,需要对照实现时再打开附录里的核心摘录 或 GitHub 完整文件------不必在中间通读近千行粘贴代码。

可以先看下文本模型的文章,这篇是后续。

模型的使用,大差不差,去模型网站买额度,然后生成key,然后接口调用。


效果图

先去申请 可灵的 Key,可以的话充点小钱做实验。


一、快速跑通(三文件 + Git)

准备一个新目录,放入下面三个文件即可跑通可灵文生图(.env.local 勿提交到 Git)。

文件 作用
index-keling.html 前端单页:拼 URL、轮询、用 img 展示结果图
server.js 后端:读环境变量、签 JWT、转发 /kling/v1/...
.env.local(自建) 配置 ACCESS_KEY_IDACCESS_KEY_SECRET

克隆仓库:

bash 复制代码
git clone https://github.com/frontzhm/text-model.git
cd text-model

仓库主页: github.com/frontzhm/te...

.env.local 示例(与 server.js 同目录):

env 复制代码
ACCESS_KEY_ID=你的AccessKey
ACCESS_KEY_SECRET=你的SecretKey
# 可选:KLING_API_ORIGIN=https://api-beijing.klingai.com

启动:

bash 复制代码
node server.js
# 另开终端,用静态服务打开页面(避免 file:// 下 ES Module 限制)
npx --yes serve .
# 浏览器访问 /index-keling.html,「代理」填 http://127.0.0.1:3000

二、为什么要有「后端」这一层?

可灵 API 与很多厂商一样,要求:

  1. 鉴权 :用 AccessKey + SecretKey 按固定规则生成 JWT ,放在 Authorization: Bearer <token> 里;
  2. HTTPS + 指定域名 :国内新系统常用 https://api-beijing.klingai.com (与旧域名不同,用错域容易出现 401 / Auth failed);
  3. 浏览器限制:Secret 不能进前端;也不适合在页面里实现签名逻辑。

因此加一层 BFF :本仓库的 server.js 负责读 .env.local签发 JWT 、把 /kling/v1/... 转发到可灵域名;浏览器只访问本地 http://127.0.0.1:3000


三、后端:server.js 里三件事

3.1 读环境变量

从项目根目录的 .env.local / .env 按行解析 KEY=value,例如:

  • ACCESS_KEY_ID / ACCESS_KEY_SECRET(或 KLING_* 别名)
  • 可选:KLING_API_ORIGIN(默认 https://api-beijing.klingai.com

3.2 生成 JWT(与官方 Python jwt.encode 一致)

  • Headeralg=HS256typ=JWT
  • Payloadiss = AccessKeyId,exp = now+1800s,nbf = now−5s
  • Signature :对 base64url(header).base64url(payload)HMAC-SHA256,再 Base64URL

使用 Node 内置 crypto.createHmac ,无需 jsonwebtoken 包。

3.3 反向代理:路径「前缀剥离」+ 上游拼接

浏览器请求例如:http://127.0.0.1:3000/kling/v1/images/generations

  1. 剥前缀 /kling → 可灵 REST 路径 /v1/images/generations
  2. 拼上游KLING_API_ORIGIN + restPath + search
  3. 带上 Authorization: Bearer <刚签的 JWT> 转发 fetch,原样回写 status 与 body。

restPath 必须 /v1/ 开头且不含 ..,防止代理滥用。


四、前端:index-keling.html 在做什么?

技术栈:Vue 3(CDN ESM) 。页面不存 AK/SK ,只填代理根地址、Prompt、resolution / aspect_ratio 等。

4.1 创建任务(POST)

base = 代理根(去掉末尾 /),拼接提交地址:

text 复制代码
endpoint = base + "/kling/v1/images/generations"

body 为 JSON payload (字段以官方文档为准),示例含 promptnegative_promptaspect_ratioresolution1k 一般比 2k 更省)。

响应里取 data.task_id

4.2 轮询(GET)------URL 拼接

text 复制代码
resultUrl = endpoint + "/" + encodeURIComponent(task_id)

resultUrl 定时 GET,读 data.task_statussubmitted / processing 继续;failed 报错;否则解析 data.task_result.images[0].url

4.3 「图片拼接」指什么?(不是多图拼画布)

  • 接口 URLbase + 固定路径 + / + encodeURIComponent(id)
  • 展示 :先把 imgUrl 设为 loading 图,成功后改为结果里的 HTTPS 图片 URL<img :src="imgUrl"> 由浏览器再去拉 CDN 图。

五、一次点击「Generate」的时序

sequenceDiagram participant B as 浏览器 index-keling.html participant S as server.js 代理 participant K as api-beijing.klingai.com B->>S: POST /kling/v1/images/generations + JSON payload S->>S: 签发 JWT S->>K: POST /v1/images/generations + Bearer JWT K-->>S: 200 + task_id S-->>B: 透传 JSON loop 轮询 B->>S: GET /kling/v1/images/generations/{task_id} S->>K: GET /v1/images/generations/{task_id} + Bearer JWT K-->>S: task_status + task_result... S-->>B: 透传 JSON end B->>B: imgUrl = task_result.images[0].url

六、省钱与排错

  • 分辨率payload.resolution1k 通常比 2k 更省(以官方计费为准)。
  • 401 / Auth failed :核对 北京域 、AK/SK、重启 node server.js 后是否读到 .env.local
  • 422 / 字段错误 :对照当前模型文档改 payload 字段名。

七、仓库文件对照

内容 文件
前端单页 index-keling.html
JWT + 代理 + DeepSeek 其它路由 server.js
环境说明 README.md

八、后续(语音等)

可按同一模板扩展:鉴权方式 → 是否需代理 → 前端拼 URL 还是拼流 ;语音若走流式或 WebSocket,「拼接」更多在 chunk 缓冲与解码,建议另开一篇写。


附录 A:核心代码摘录(与仓库一致)

完整可运行代码请以仓库为准;下面仅保留与可灵最相关的片段。

A.1 server.js:JWT + 代理(节选)

js 复制代码
const KLING_API_ORIGIN = (
  process.env.KLING_API_ORIGIN || 'https://api-beijing.klingai.com'
).trim()
const KLING_PATH_PREFIX = '/kling'

function signKlingJwt(accessKeyId, accessKeySecret) {
  const now = Math.floor(Date.now() / 1000)
  const header = { alg: 'HS256', typ: 'JWT' }
  const payload = { iss: accessKeyId, exp: now + 1800, nbf: now - 5 }
  const h = toBase64Url(JSON.stringify(header))
  const p = toBase64Url(JSON.stringify(payload))
  const signingInput = `${h}.${p}`
  const sig = crypto
    .createHmac('sha256', accessKeySecret)
    .update(signingInput)
    .digest('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g, '')
  return `${signingInput}.${sig}`
}

// createServer 内:pathname 以 /kling 开头则 await proxyKlingRequest(...)
// proxyKlingRequest:restPath = pathname 去掉 /kling;拼 targetUrl;Bearer 调用 fetch(upstream)

toBase64UrlreadRequestBodyCORSloadDotEnv 及 DeepSeek 路由见仓库文件。)

A.2 index-keling.html:提交与轮询 URL(节选)

js 复制代码
const endpoint = `${base}/kling/v1/images/generations`
const payload = {
  prompt: prompt.value.trim(),
  negative_prompt: negativeWords,
  aspect_ratio: aspectRatio.value,
  resolution: resolution.value
}
const res = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'application/json' }, body: JSON.stringify(payload) })
const id = (await res.json()).data?.task_id
const resultUrl = `${endpoint}/${encodeURIComponent(id)}`
// 循环 fetch(resultUrl) 直到非 processing/submitted ...

(Vue template<style>、localStorage 与错误处理见仓库完整 HTML。)


附录 B:完整源码一键打开(Raw)

便于整文件复制:


相关推荐
清空mega4 小时前
动手学深度学习——样式迁移
人工智能·深度学习
yuanzhengme4 小时前
AI【应用 04】FunASR离线文件转写服务开发指南(实践篇)
人工智能·macos·xcode
Reart4 小时前
从0解构tinyWeb项目--(Day:2)
javascript·后端·架构
木斯佳4 小时前
前端八股文面经大全:腾讯CSIG实习面(2026-04-10)·面经深度解析
前端·ai·xss·埋点·实习面经
夏暖冬凉4 小时前
npm发布流程(记录遇到的问题)
前端·npm·node.js
XPoet4 小时前
AI 编程工程化:Subagent——给你的 AI 员工打造协作助手
前端·后端·ai编程
慧知AI4 小时前
Kimi 2.6 技术深度解析:5秒响应背后的架构突破
人工智能
卷卷说风控4 小时前
单独一个工具再强,不如一套工具链协同|卷卷养虾记 · 十二篇
人工智能
黑金IT4 小时前
vLLM本地缓存实战,重复提交直接复用不浪费算力
人工智能·缓存