6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Stable Diffusionで空いた時間にLineスタンプ大量生成!

Last updated at Posted at 2023-12-27

こんにちは、ひよっこエンジニア兼デザイナーのウエハラ シンペイです。

プログラミングを初めて早1ヶ月。今回は話題のAIを使って何かできないかと思い、空いた時間にLineスタンプメーカーを作ってみようと思います!レッツ小銭稼ぎ!

Stable Diffusion×LINEでスタンプ用のイラストをつくる

色々方法はあると思うのですが、今回は基本のプロンプトを記述して、なおかつ空き時間にサクッと送って置けるようにLINE Message APIを使って構築していきます。

素材.png

1.Hugging Faceでアカウント作成

Hugging Faceでアカウント作成し、導入方法や使用する上でのライセンスについてを調べると、アクセストークンの発行をしました。モデルについてはStabble Diffsionはこちらを使用(詳しいことはわかってないけど人気だったんで笑)
スクリーンショット 2023-12-28 3.01.21.png

2.Node.jsでコードを書いてLINEで送ると画像生成

hugging face、AWS S3、LINE Messaging APIと名前は知ってても初めて自分で設定したのでかなり苦戦しましたが無事画像生成することができました。特にAWSはUIが変わったのか参考記事で書いてある内容と違っててかなり苦戦して、なんとか自力で設定しましたが、多分セキュリティ的には良くない方法で実装しているので、勉強不足を痛感しました。

コードはこちら
sample.js

import express from 'express';
import { Client, middleware } from '@line/bot-sdk';
import fetch from 'node-fetch';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
import { randomBytes } from 'crypto';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// AWS SDKの設定
const s3Client = new S3Client({
    region: 'ap-northeast-1',
    credentials: {
        accessKeyId: 'XXXXXXXXXXXXXXXXXXXXXXXXX',
        secretAccessKey: 'XXXXXXXXXXXXXXXXXXXXXXXXX'
    }
});
const bucketName = 'stampmaker';

const config = {
    channelAccessToken: 'XXXXXXXXXXXXXXXXXXXXXXXXX',
    channelSecret: 'XXXXXXXXXXXXXXXXXXXXXXXXX',
};

const client = new Client(config);

const app = express();

app.post('/webhook', middleware(config), async (req, res) => {
    try {
        const results = await Promise.all(req.body.events.map(handleEvent));
        res.json(results);
    } catch (err) {
        console.error(err);
        res.status(500).end();
    }
});

async function query(data) {
    const response = await fetch(
        "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0",
        {
            headers: { Authorization: "Bearer XXXXXXXXXXXXXXXXXXXXXXXXX" },
            method: "POST",
            body: JSON.stringify(data),
        }
    );
    return response;
}

async function handleEvent(event) {
    if (event.type !== 'message' || event.message.type !== 'text') {
        return null;
    }

    const userText = event.message.text;
    const prompt = createPrompt(userText);

    const modifiedPrompt = `${prompt}, pose 1`;
    const response = await query({ inputs: modifiedPrompt });

    const fileName = `tempImage_1_${generateRandomString()}.png`;
    const imagePath = path.join(__dirname, fileName);
    await saveImage(response, imagePath);

    const imageUrl = await uploadToS3(imagePath, fileName);
    await sendImage(event.replyToken, imageUrl);

    fs.unlinkSync(imagePath);
    console.log('success');
    console.log(imageUrl);
}

async function saveImage(response, filePath) {
  const arrayBuffer = await response.arrayBuffer();
  const buffer = Buffer.from(arrayBuffer);
  return fs.promises.writeFile(filePath, buffer);
}

async function uploadToS3(filePath, fileName) {
  const fileContent = fs.readFileSync(filePath);
  const uploadParams = {
      Bucket: 'xxxxxxxxxx', // 文字列としてバケット名を指定
      Key: fileName,
      Body: fileContent,
      ContentType:'image/png',
  };

  await s3Client.send(new PutObjectCommand(uploadParams));
  return `https://${uploadParams.Bucket}.s3.amazonaws.com/${fileName}`;
}

function generateRandomString() {
    return randomBytes(16).toString('hex');
}

async function sendImage(replyToken, imageUrl) {
    const message = {
        type: 'image',
        originalContentUrl: imageUrl,
        previewImageUrl: imageUrl
    };
    await client.replyMessage(replyToken, message);
}

function createPrompt(userText) {
  return `${userText} square, simple background, animal, Only one, -human , -realistic tone,`;
}


app.listen(3000, () => {
    console.log('Application is running on port 3000');
});


何はともあれプロンプトも細かく調整しながら、実際にできた画像は!

かなりかわいい!王道のかわいいワンちゃんでございます!

3.LINEスタンプメーカーでテキストを入れて登録

LINEスタンプメーカーを使って画像の背景を消したり、テキストを追加をしていきます。最低8個登録すれば登録・販売することができます!

  

ここまでが画像生成からLINE Store出品に向けたざっくりした流れになります!慣れればかなり早く作れそうで、あとはプロンプトを工夫して生成AIならではのスタンプも作れるかもしれません。

例えば1つ当たりの月平均¥10でも100個作れば月に1000円!1000個なら1万円!10000個なら!?

まぁ、そううまくはいかないでしょうが、初めて触ったプラットフォームが多い中でまずは一連の流れができてよかったです。あとは効率化とスタンプのアイデア次第で不労収益がっぽがっぽや!!

権利関係はこちらをチェック

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?