mirror of
https://github.com/moeru-ai/airi.git
synced 2026-08-14 00:48:06 +00:00
refactor(docs,telegram-bot): remove sharp
This commit is contained in:
+1
-1
@@ -41,6 +41,7 @@
|
||||
"@intlify/unplugin-vue-i18n": "^11.0.1",
|
||||
"@mdit/plugin-footnote": "^0.22.3",
|
||||
"@mdit/plugin-tasklist": "^0.22.2",
|
||||
"@napi-rs/image": "^1.9.1",
|
||||
"@proj-airi/stage-ui": "workspace:^",
|
||||
"@radix-ui/colors": "^3.0.0",
|
||||
"@types/hast": "^3.0.4",
|
||||
@@ -54,7 +55,6 @@
|
||||
"markdown-it-anchor": "^9.2.0",
|
||||
"minisearch": "^7.2.0",
|
||||
"postcss": "^8.5.6",
|
||||
"sharp": "^0.34.5",
|
||||
"shiki": "^3.20.0",
|
||||
"tinyglobby": "^0.2.15",
|
||||
"tsx": "^4.21.0",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import path from 'node:path'
|
||||
import process from 'node:process'
|
||||
|
||||
import { readdir, readFile, rm, stat } from 'node:fs/promises'
|
||||
import { readdir, readFile, rm, stat, writeFile } from 'node:fs/promises'
|
||||
|
||||
import sharp from 'sharp'
|
||||
import { Transformer } from '@napi-rs/image'
|
||||
|
||||
const SOURCE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp']
|
||||
|
||||
@@ -21,7 +21,8 @@ async function transform(filePath: string): Promise<any> {
|
||||
path.dirname(filePath),
|
||||
`${path.basename(filePath, path.extname(filePath))}.avif`,
|
||||
)
|
||||
await sharp(await readFile(filePath)).toFile(dist)
|
||||
const avifBuffer = await new Transformer(await readFile(filePath)).avif()
|
||||
await writeFile(dist, avifBuffer)
|
||||
await rm(filePath)
|
||||
console.info(`√ ${filePath} -> ${dist}`)
|
||||
}
|
||||
@@ -34,9 +35,7 @@ async function main() {
|
||||
}
|
||||
|
||||
await Promise.all(files.map(f => stat(f)))
|
||||
await Promise.allSettled(
|
||||
files.map(file => transform(file)),
|
||||
)
|
||||
await Promise.allSettled(files.map(file => transform(file)))
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"test:run": "vitest run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@moeru/std": "catalog:",
|
||||
"uncrypto": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Generated
+1128
-335
File diff suppressed because it is too large
Load Diff
+3
-3
@@ -23,8 +23,8 @@ overrides:
|
||||
|
||||
catalog:
|
||||
'@guiiai/logg': 1.1.0
|
||||
'@moeru/eslint-config': 0.1.0-beta.13
|
||||
'@moeru/std': 0.1.0-beta.13
|
||||
'@moeru/eslint-config': 0.1.0-beta.14
|
||||
'@moeru/std': 0.1.0-beta.14
|
||||
'@proj-airi/drizzle-duckdb-wasm': ^0.4.29
|
||||
'@types/audioworklet': ^0.0.92
|
||||
'@xsai-ext/providers-cloud': ^0.4.0-beta.12
|
||||
@@ -57,6 +57,7 @@ catalogs:
|
||||
|
||||
onlyBuiltDependencies:
|
||||
- '@discordjs/opus'
|
||||
- '@napi-rs/image'
|
||||
- '@ffmpeg-installer/darwin-arm64'
|
||||
- '@parcel/watcher'
|
||||
- bufferutil
|
||||
@@ -69,7 +70,6 @@ onlyBuiltDependencies:
|
||||
- msw
|
||||
- onnxruntime-node
|
||||
- protobufjs
|
||||
- sharp
|
||||
- simple-git-hooks
|
||||
- spawn-sync
|
||||
- utf-8-validate
|
||||
|
||||
@@ -49,10 +49,10 @@
|
||||
"es-toolkit": "^1.43.0",
|
||||
"fluent-ffmpeg": "^2.1.3",
|
||||
"grammy": "^1.38.4",
|
||||
"@napi-rs/image": "^1.9.1",
|
||||
"nanoid": "^5.1.6",
|
||||
"p-limit": "^7.2.0",
|
||||
"pg": "^8.16.3",
|
||||
"sharp": "^0.34.5",
|
||||
"telegram": "^2.26.22",
|
||||
"uuid": "^13.0.0",
|
||||
"valibot": "^1.2.0"
|
||||
|
||||
@@ -11,7 +11,6 @@ import { env } from 'node:process'
|
||||
|
||||
import ffmpegInstaller from '@ffmpeg-installer/ffmpeg'
|
||||
import ffmpeg from 'fluent-ffmpeg'
|
||||
import Sharp from 'sharp'
|
||||
|
||||
import { useLogg } from '@guiiai/logg'
|
||||
import { generateText } from '@xsai/generate-text'
|
||||
@@ -19,6 +18,7 @@ import { message } from '@xsai/utils-chat'
|
||||
|
||||
import { findStickerDescription, recordSticker } from '../models'
|
||||
import { div, span, ul } from '../prompts/utils'
|
||||
import { toPngBase64FromFile } from './image'
|
||||
|
||||
// Set path to FFmpeg binaries
|
||||
ffmpeg.setFfmpegPath(ffmpegInstaller.path)
|
||||
@@ -88,17 +88,10 @@ export async function interpretAnimatedSticker(bot: Bot, msg: Message, sticker:
|
||||
logger.withField('sampled', sampled).log('Sampled frames')
|
||||
|
||||
// Process frames with Sharp
|
||||
const frames = await Promise.all(sampled.map(async (framePath, index) => {
|
||||
const frameBuffer = await Sharp(framePath)
|
||||
.resize(512, 512)
|
||||
.png()
|
||||
.toBuffer()
|
||||
return {
|
||||
index,
|
||||
buffer: frameBuffer,
|
||||
base64: Buffer.from(frameBuffer).toString('base64'),
|
||||
}
|
||||
}))
|
||||
const frames = await Promise.all(sampled.map(async (framePath, index) => ({
|
||||
index,
|
||||
base64: await toPngBase64FromFile(framePath),
|
||||
})))
|
||||
logger.withField('sampled_frames', sampled).log('Normalized the frames')
|
||||
|
||||
// STAGE 1: Process each frame individually
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Buffer } from 'node:buffer'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
|
||||
import { ResizeFilterType, Transformer } from '@napi-rs/image'
|
||||
|
||||
type ImageInput = ArrayBuffer | Buffer | Uint8Array
|
||||
|
||||
function toUint8Array(input: ImageInput): Uint8Array {
|
||||
return input instanceof Uint8Array ? input : new Uint8Array(input)
|
||||
}
|
||||
|
||||
export async function toPngBase64(input: ImageInput) {
|
||||
const transformer = new Transformer(toUint8Array(input))
|
||||
transformer.resize(512, 512, ResizeFilterType.Lanczos3)
|
||||
const pngBuffer = await transformer.png()
|
||||
return Buffer.from(pngBuffer).toString('base64')
|
||||
}
|
||||
|
||||
export async function toPngBase64FromFile(filePath: string) {
|
||||
const buffer = await readFile(filePath)
|
||||
return toPngBase64(buffer)
|
||||
}
|
||||
@@ -3,16 +3,14 @@ import type { Message, PhotoSize } from 'grammy/types'
|
||||
|
||||
import type { BotContext } from '../types'
|
||||
|
||||
import { Buffer } from 'node:buffer'
|
||||
import { env } from 'node:process'
|
||||
|
||||
import Sharp from 'sharp'
|
||||
|
||||
import { embed } from '@xsai/embed'
|
||||
import { generateText } from '@xsai/generate-text'
|
||||
import { message } from '@xsai/utils-chat'
|
||||
|
||||
import { findPhotosDescriptions, recordPhoto } from '../models'
|
||||
import { toPngBase64 } from './image'
|
||||
|
||||
export async function interpretPhotos(state: BotContext, msg: Message, photos: PhotoSize[]) {
|
||||
try {
|
||||
@@ -25,8 +23,7 @@ export async function interpretPhotos(state: BotContext, msg: Message, photos: P
|
||||
const photoResArray = await Promise.all(files.map(file => fetch(`https://api.telegram.org/file/bot${state.bot.api.token}/${file.file_path}`)))
|
||||
|
||||
const buffers = await Promise.all(photoResArray.map(photoRes => photoRes.arrayBuffer()))
|
||||
const pngResizedBuffers = await Promise.all(buffers.map(buffer => Sharp(buffer).resize(512, 512).png().toBuffer()))
|
||||
const photoBase64s = pngResizedBuffers.map(buffer => Buffer.from(buffer).toString('base64'))
|
||||
const photoBase64s = await Promise.all(buffers.map(buffer => toPngBase64(buffer)))
|
||||
|
||||
await Promise.all(photoBase64s.map(async (base64, index) => {
|
||||
const req = {
|
||||
|
||||
@@ -2,11 +2,8 @@ import type { GenerateTextOptions } from '@xsai/generate-text'
|
||||
import type { Bot } from 'grammy'
|
||||
import type { Message, Sticker } from 'grammy/types'
|
||||
|
||||
import { Buffer } from 'node:buffer'
|
||||
import { env } from 'node:process'
|
||||
|
||||
import Sharp from 'sharp'
|
||||
|
||||
import { useLogg } from '@guiiai/logg'
|
||||
import { embed } from '@xsai/embed'
|
||||
import { generateText } from '@xsai/generate-text'
|
||||
@@ -15,6 +12,7 @@ import { message } from '@xsai/utils-chat'
|
||||
import { findStickerDescription, recordSticker } from '../models'
|
||||
import { div, span } from '../prompts/utils'
|
||||
import { interpretAnimatedSticker } from './animated-sticker'
|
||||
import { toPngBase64 } from './image'
|
||||
|
||||
export async function interpretSticker(bot: Bot, msg: Message, sticker: Sticker) {
|
||||
const logger = useLogg('interpretSticker').useGlobalConfig()
|
||||
@@ -39,7 +37,7 @@ export async function interpretSticker(bot: Bot, msg: Message, sticker: Sticker)
|
||||
const file = await bot.api.getFile(sticker.file_id)
|
||||
const stickerRes = await fetch(`https://api.telegram.org/file/bot${bot.api.token}/${file.file_path}`)
|
||||
const buffer = await stickerRes.arrayBuffer()
|
||||
const stickerBase64 = Buffer.from(await Sharp(buffer).resize(512, 512).png().toBuffer()).toString('base64')
|
||||
const stickerBase64 = await toPngBase64(buffer)
|
||||
|
||||
const req = {
|
||||
apiKey: env.LLM_VISION_API_KEY!,
|
||||
|
||||
Reference in New Issue
Block a user