当前位置:AIGC资讯 > AIGC > 正文

无需魔法,教你Midjourney随意用【内附源码】【示例】

感谢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做的样例,不要在意页面美感,主要做接口实验使用。

示例:传送门

更新时间 2023-12-06