Bing AI 生成每日图片

前段时间刷到一篇分享 liruifengv/daily-poetry-image:用Bing-AI的文生图功能结合诗词api生成对应图片。联想到之前fork的bing-wallpaper项目,就来简单改造下。

bing-wallpaper

bing-wallpaper项目比较简单,就是利用GitHub-action跑定时任务爬取Bing每日壁纸链接,随后更新README.md文档。

这个项目是用java写的,当时直接fork的niumoo/bing-wallpape,修改下ci的配置就能跑了。目前已经稳定运行快两年了,每天会跑两次防止更新遗漏,会有一次异常部署是因为当时还没更新今日壁纸。

改造的思路就是利用Bing-AI来代替Bing每日壁纸,每天都是AI-Generate图片。

bing-ai-poetry

Github 地址 Mulander-J/bing-ai-poetry

前提准备,需要有edge浏览器+账号,以及科学上网。能正常访问 https://bing.com/create,并生成一次图片,记录cookie后面会用到。

文生图的文字部分由今日诗词api随机生成。

bash 复制代码
curl https://v1.jinrishici.com/all

{
  "content" : "正蹇驴吟影,茶烟灶冷,酒亭门闭。",
  "origin" : "无闷·催雪",
  "author" : "吴文英",
  "category" : "古诗文-食物-写茶"
}

liruifengv/daily-poetry-image 的基础上,砍掉原有的前端项目(不需要前端渲染,自带README.md足够。)

diff 复制代码
- website

稍微修改入口文件 bin/cli.ts

之前在本地测试的时候,因为网络原因图片经常只能下到一两张,且只有一半的数据。修改的部分主要是将主函数套上async,然后就可以在内部await图片下载和读写事务,确保进程退出时图片不会下到一半。

另外下载好图片的同时会同步修改README.md文件,只需要append新内容就行了。

核心的getImageBySentence 随机诗词文生图方法原项目都封装好了。

ts 复制代码
import { getImageBySentence } from "../src/get-up";
import type { Response } from "../src/types";
import path from "path";
import fs from "fs";
import stream from "stream";
import { promisify } from "util";

const pipeline = promisify(stream.pipeline);

async function init() {
   const cwd = process.cwd();

   const argv = require("minimist")(process.argv.slice(2));
   if (argv.cookie && typeof argv.cookie !== 'boolean') { // 此处兼容 --cookie="xx" 和 --cookie "xx"
       try {
           // const res =  {
           //     images: [
           //         'https://tse1.mm.bing.net/th/id/OIG.0lT30AZgF0Y9TGnssoUu',
           //         'https://tse2.mm.bing.net/th/id/OIG.AYKgb1ftqrAfxCfwGjCs',
           //         'https://tse1.mm.bing.net/th/id/OIG.GcNrrihRgfhlHOwiRtR.'
           //     ],
           //     content: '关山别荡子,风月守空闺。',
           //     origin: '昔昔盐',
           //     author: '薛道衡',
           //     category: '古诗文-抒情-离别'
           // }
           const res: Response = await getImageBySentence(argv.cookie);
           console.log("Create Successful: ", res);

           const imagesPath = path.join(cwd, "images");
           if (!fs.existsSync(imagesPath)) {
               fs.mkdirSync(imagesPath);
           }

           // 在 images 目录下,创建一个以时间戳命名的文件夹,将图片放入其中
           const imagesFolderName = Date.now().toString();
           const imagesFolderPath = path.join(imagesPath, imagesFolderName);
           if (!fs.existsSync(imagesFolderPath)) {
               fs.mkdirSync(imagesFolderPath);
           }
           const images = res.images
           let imgPaths:any[] = []
           // 将图片放入 images 目录下的文件夹中
           for(let i = 0; i < images.length; i++){
                // images 中是网络url,请求图片,将图片保存到 images 目录下的文件夹中
               const imageFileName = `${i}.jpg`;
               const imageFilePath = path.join(imagesFolderPath, imageFileName);
               const imageDocPath = `./images/${imagesFolderName}/${imageFileName}`
               imgPaths.push(`![${imagesFolderName}_${imageFileName}](${imageDocPath})[${imageFileName}](${images[i]})`)

               // 下载图片
               console.log('fetching...', images[i])
               const res:any = await fetch(images[i])
               if (!res.ok) throw new Error(`unexpected response ${res.statusText}`);
               await pipeline(res.body, fs.createWriteStream(imageFilePath)).catch((e) => {
                   console.error("Something went wrong while saving the image", e);
               });
               console.log('>fetched', images[i])
           }
           console.log('Fetch Images Ended')

           const options = { timeZone: "Asia/Shanghai", hour12: false };
           const outputData = {
               ...res,
               date: new Date().toLocaleString("zh-CN", options),
               localImagesPath: imagesFolderName,
           };

           const contentFile = path.join(imagesFolderPath, 'index.json');

           fs.writeFileSync(contentFile, JSON.stringify(outputData));

           const rowHead = `> ${res.content} ------ ${res.author}《${res.origin}》\n`
           let appendCtx = `|${imgPaths.map(_=>'      ').join('|')}|\n`
           appendCtx += `|${imgPaths.map(_=>' :----: ').join('|')}|\n`
           appendCtx += `|${imgPaths.join('|')}|`
           fs.appendFileSync('./README.md', [
               '',
               rowHead,
               appendCtx,
               ''
           ].join('\n'))

           // 缓冲等待,确保未捕获的异步任务都能跑完
           console.log('Wating Sec...')
           setTimeout(() => {
               process.exit(0);
           }, 5 * 1000);
       } catch (e) {
           console.error(e);
           process.exit(1);
       }
   } else {
       throw new Error("Please provide a cookie using the --cookie argument");
   }
}

init().catch((e) => {
   console.error(e);
});

以及,处理Bing接口返回时,获取图片数据是采用正则/src="([^"]*)"/g全局匹配的,偶尔会跑出来几张https://r.bing.com/rp/xxx的乱入图片需要剔除。

ts 复制代码
    // /src/bing-image-creator.ts
    parseResult(result: string) {
        console.log("Parsing result...");
        // Use regex to search for src=""
        const regex = /src="([^"]*)"/g;
        const matches = [...result.matchAll(regex)].map((match) => match[1]);
        // Remove Bad Images(https://r.bing.com/rp/xxx)
        const safe_image_links = matches.filter(link => !/r.bing.com\/rp/i.test(link))
        // Remove size limit
        const normal_image_links = safe_image_links.map(link => (link.split("?w=")[0]));
        // Remove duplicates
        const unique_image_links = [...new Set(normal_image_links)];
        // No images
        if (unique_image_links.length === 0) {
            throw new Error("error_no_images");
        }
        return unique_image_links;
    }

完工。接下来就是actions定时跑任务了, 一切正常。

相关推荐
tuokuac19 分钟前
nginx配置前端请求转发到指定的后端ip
前端·tcp/ip·nginx
程序员爱钓鱼23 分钟前
Go语言实战案例-开发一个Markdown转HTML工具
前端·后端·go
万少1 小时前
鸿蒙创新赛 HarmonyOS 6.0.0(20) 关键特性汇总
前端
还有多远.1 小时前
jsBridge接入流程
前端·javascript·vue.js·react.js
蝶恋舞者1 小时前
web 网页数据传输处理过程
前端
非凡ghost1 小时前
FxSound:提升音频体验,让音乐更动听
前端·学习·音视频·生活·软件需求
吃饭最爱2 小时前
html的基础知识
前端·html
我没想到原来他们都是一堆坏人2 小时前
(未完待续...)如何编写一个用于构建python web项目镜像的dockerfile文件
java·前端·python
前端Hardy2 小时前
HTML&CSS:有趣的漂流瓶
前端·javascript·css
前端Hardy2 小时前
HTML&CSS :惊艳 UI 必备!卡片堆叠动画
前端·javascript·css