感谢laf提供云资源赞助,小伙伴可白piao用来做测试。
感谢laf团队、白夜、米开朗基杨@sealos.io的热心布道 ,life is short, u need laf : )
欢迎你也来加入laf开发。
正好现在laf在做一个活动,一起搞起来吧人人都能接入 Midjourney
目标
由于Midjourney官方并没有提供api接口,有大佬开封装了通过discord间接操作使用midjourney的nodejs包,我们通过在自己的程序中集成这个三方库来完成midjourney的使用,这是代码层面的核心事情。另外就是大家都懂的原因没办法访问midjourney,我们通过https://laf.dev 的新加坡节点Serverless来运行我们的程序,我们再通过访问在laf部署的程序来连接midjourney服务。
注册laf账号
Laf是环界云开发的一个Serverless框架,它可以帮助开发者快速构建具有AI能力的分布式应用。使用Laf,你可以像写博客一样轻松地编写代码,并随时随地快速发布上线应用。
现在Laf提供免费资源供开发者测试使用,这里我们直接用免费的就足够跑程序了。
laf服务区分杭州和新加坡,从不同域名进入注册不同区域的账号。
新加坡:新加坡地址 (今天的midjourney我们要用新加坡的服务)
杭州:杭州地址
手机号码短信注册,过程太简单,这里不多说了。
编写函数
先在云开发面板添加一个函数,取个自己喜欢的函数名,我这里取名:midjourney
添加函数代码
import cloud from '@lafjs/cloud' import { Midjourney, MidjourneyMessage } from 'midjourney' const SERVER_ID = '' // Midjourney 服务 ID const CHANNEL_ID = '' // Midjourney 频道 ID const SALAI_TOKEN = '' // Midjourney 服务 Token const Limit = 100 const MaxWait = 3 const client = new Midjourney({ ServerId: SERVER_ID, ChannelId: CHANNEL_ID, SalaiToken: SALAI_TOKEN, Debug: true, SessionId: SALAI_TOKEN, Limit: Limit, MaxWait: MaxWait }); export default async function (ctx: FunctionContext) { const { type, param } = ctx.body switch (type) { case 'RetrieveMessages': return await RetrieveMessages(param) case 'imagine': return await imagine(param) case 'upscale': return await upscale(param) case 'variation': return await variation(param) } } // 查询最近消息 async function RetrieveMessages(param) { console.log("RetrieveMessages") const client = new MidjourneyMessage({ ChannelId: CHANNEL_ID, SalaiToken: SALAI_TOKEN, }); const msg = await client.RetrieveMessages(); console.log("RetrieveMessages success ", msg) return msg } // 创建生图任务 async function imagine(param) { console.log("imagine", param) const { question, msg_Id } = param const msg = await client.Imagine( `[${msg_Id}] ${question}`, (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); } ); console.log("imagine success ", msg) return true } // upscale 放大图片 async function upscale(param) { console.log("upscale", param) const { question, index, id, url } = param const hash = url.split("_").pop()?.split(".")[0] ?? "" console.log(hash) const msg = await client.Upscale( question, index, id, hash, (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); } ); console.log("upscale success ", msg) return msg } // variation 变换图片 async function variation(param) { console.log("variation", param) const client = new Midjourney({ ServerId: SERVER_ID, ChannelId: CHANNEL_ID, SalaiToken: SALAI_TOKEN, Debug: true, SessionId: SALAI_TOKEN, Limit: Limit, MaxWait: 100 }); const { question, index, id, url } = param const hash = url.split("_").pop()?.split(".")[0] ?? "" const msg = await client.Variation( question, index, id, hash, (uri: string, progress: string) => { console.log("loading", uri, "progress", progress); } ); console.log("variation success ", msg) return msg }
添加相关函数所需的依赖:
填写关键配置信息,用于初始化一个midjourney客户端:
const SERVER_ID = '' // Midjourney 服务 ID
const CHANNEL_ID = '' // Midjourney 频道 ID
const SALAI_TOKEN = '' // Midjourney 服务 Token
这三项配置信息可以白piao @米开朗基杨@sealos.io 提供的满级账号用来测试够了,仔细看前文的活动帖即可获得。
如果有自己的账号,可以登录discord在频道发一条信息,F12在请求中找到。
完成以上操作步骤,点击laf云开发节点的发布,即可测试midjourney api接口调用。
接口调试:
先点击发布左侧的链接,复制。这就是我们写好的midjourney服务api链接了。
我这里用postman调试api接口:
先来调用生成图片
查询历史任务:
从历史任务中获得我们发送的生图任务和结果。
查询接口一次返回多条数据,返回的是这个频道中的数据,目前这个测试配置信息是多人共享的,所以能查到其他人生成的图片任务。
查询到结果后,记得提取出:id、content、url这几个字段,后面放大和重新绘制会用到。
来看看生成的图片效果吧。
一次生图任务会返回四张预览图供你选择,选择一张你喜欢的,执行放大即可获得高清大图。
这里我们把第二张图放大看看:
看看放大的图片效果:
非常高清,很有质感。midjourney 杠杆滴。
小伙伴可能会遇到生成图片结果的url链接无法访问的情况,是因为大家都懂的原因。
这里我们仍然可以继续使用laf提供的云存储能力来转存图片,示例代码如下:
import cloud from '@lafjs/cloud' import axios from 'axios' import { S3 } from "@aws-sdk/client-s3"; const s3Client = new S3({ endpoint: process.env.OSS_EXTERNAL_ENDPOINT, region: process.env.OSS_REGION, credentials: { accessKeyId: process.env.OSS_ACCESS_KEY, secretAccessKey: process.env.OSS_ACCESS_SECRET }, forcePathStyle: true, }) export default async function (ctx: FunctionContext) { console.log('storage image') const { url } = ctx.body if (!url) { return { err: "url is empty" } } let key = '' if (url.indexOf('https://cdn.discordapp.com/') == 0) { key = url.replace('https://cdn.discordapp.com/', '') } if (url.indexOf('https://media.discordapp.net/') == 0) { key = url.replace('https://media.discordapp.net/', '') } await uploadImgToMinio(url, key); return { data: 'https://<你的云存储bucket>.site.laf.dev/' + key } } async function uploadImgToMinio(imgurl, key) { const { data } = await axios.get(imgurl, { responseType: 'arraybuffer' }); const buffer = Buffer.from(data, 'binary'); await s3Client.putObject({ Bucket: <你的云存储bucket>, Key: key, Body: buffer, ContentType: 'application/octet-stream' }); }
这里将原始的图片路径完全一致的转存到laf云存储中保存,保存成功后我们就可以通过laf云存储的bucket链接地址来访问图片了。
更多玩法等你来挖掘,就讲到这里。
下面是我用laf做的样例,不要在意页面美感,主要做接口实验使用。
示例:传送门
midjourneyurltokenclidiscord云存储appapicodeiosapi接口开发者serverlesscdnexodebugcepat快速发布客户端查询接口rag预览图nodejs免费资源分布式sdk快速构建aws放大图片