Alvi
Alvi4w ago

Convex image compression

Does convex provide any plugin to compress images
6 Replies
Convex Bot
Convex Bot4w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
jamwt
jamwt4w ago
no, but we want to make a component for a CDN that offers this soon
Riki
Riki4w ago
@Alvi in case that helps, this is what I am doing so far: 1. Install sharp js package, and register it in your convex.json file
{
"node": {
"externalPackages": [
"sharp"
]
}
}
{
"node": {
"externalPackages": [
"sharp"
]
}
}
2. Add this file in your code:
'use node'

import { v } from 'convex/values'
import { internalAction } from '../_generated/server'
import sharp from 'sharp'
import { internal } from '../_generated/api'

export const optimizeImage = internalAction({
args: {
imageUrl: v.string(),
},
handler: async (ctx, args) => {
const req = await fetch(args.imageUrl)
const body = await req.arrayBuffer()

const imageSize = body.byteLength
let quality = 100
if (imageSize < 500_000) {
quality = 1
} else if (imageSize < 1_000_000) {
quality = 80
} else if (imageSize < 2_000_000) {
quality = 70
} else if (imageSize < 5_000_000) {
quality = 65
} else if (imageSize < 10_000_000) {
quality = 55
} else if (imageSize < 20_000_000) {
quality = 45
} else {
quality = 20
}
const imageBuffer = await sharp(body) // Load input image
.resize({
width: 1920,
height: 1920,
fit: 'inside', // Ensures the image fits within 1920x1920 while keeping aspect ratio
})
.webp({ quality: quality })
.toBuffer()

const blob = new Blob([imageBuffer], { type: 'image/webp' })
const storage = await ctx.storage.store(blob)

// Store your storageId in your db.
// To link that storageId to that url, you can either pass a unique id as function argument or return a generated id here.
},
})
'use node'

import { v } from 'convex/values'
import { internalAction } from '../_generated/server'
import sharp from 'sharp'
import { internal } from '../_generated/api'

export const optimizeImage = internalAction({
args: {
imageUrl: v.string(),
},
handler: async (ctx, args) => {
const req = await fetch(args.imageUrl)
const body = await req.arrayBuffer()

const imageSize = body.byteLength
let quality = 100
if (imageSize < 500_000) {
quality = 1
} else if (imageSize < 1_000_000) {
quality = 80
} else if (imageSize < 2_000_000) {
quality = 70
} else if (imageSize < 5_000_000) {
quality = 65
} else if (imageSize < 10_000_000) {
quality = 55
} else if (imageSize < 20_000_000) {
quality = 45
} else {
quality = 20
}
const imageBuffer = await sharp(body) // Load input image
.resize({
width: 1920,
height: 1920,
fit: 'inside', // Ensures the image fits within 1920x1920 while keeping aspect ratio
})
.webp({ quality: quality })
.toBuffer()

const blob = new Blob([imageBuffer], { type: 'image/webp' })
const storage = await ctx.storage.store(blob)

// Store your storageId in your db.
// To link that storageId to that url, you can either pass a unique id as function argument or return a generated id here.
},
})
Alvi
AlviOP4w ago
thanks
jamwt
jamwt4w ago
also, I realized, I sort of lied there already is a pretty good solution to this today
jamwt
jamwt4w ago
1. use the convex R2 component ( https://www.convex.dev/components/cloudflare-r2 ) 2. use cloudflare images API and CDN While you have a little more setup to do (mostly on the cloudflare side), this is a pretty fast and cost efficient way to manage resized images
Convex
Cloudflare R2
Store and serve files from Cloudflare R2.

Did you find this page helpful?