feat: mockup generation API route using gpt-image-1

This commit is contained in:
2026-06-22 12:14:31 +02:00
parent 1ef69dc205
commit d138577a9d
+66
View File
@@ -0,0 +1,66 @@
import { NextRequest } from 'next/server'
import { getServerSession } from 'next-auth'
import { authOptions } from '@/lib/auth'
import { readFile } from 'fs/promises'
import { getTemplateImagePath, listTemplates } from '@/lib/mockupTemplates'
import type { MockupGenerateRequest } from '@/types/mockup'
function buildPrompt(req: MockupGenerateRequest): string {
const familyContext: Record<string, string> = {
'Menuiserie': 'door installed in a residential entrance or hallway, visible wall and floor context',
'Baies vitrées': 'bay window or sliding door installed in a living room with garden view',
'Carrelage': 'tiles covering the floor or wall of a modern room',
}
const context = familyContext[req.family] ?? 'product installed in an appropriate room setting'
const dimClause = req.dimensions
? ` The product dimensions are exactly ${req.dimensions} — preserve these exact proportions, do NOT resize or distort the product to fit the scene.`
: ''
const instructionClause = req.instruction ? ` Additional instruction: ${req.instruction}.` : ''
return `Replace the product in the reference scene with the provided product image (${req.productName}). Show the ${context}.${dimClause} Keep the product's exact design, texture, colors and proportions identical to the provided image. Maintain realistic perspective and lighting consistent with the scene.${instructionClause}`
}
export async function POST(req: NextRequest) {
const session = await getServerSession(authOptions)
if (!session) return Response.json({ error: 'Non authentifié' }, { status: 401 })
const apiKey = process.env.OPENAI_API_KEY
if (!apiKey) return Response.json({ error: 'OPENAI_API_KEY manquant' }, { status: 500 })
const body = await req.json() as MockupGenerateRequest
const templates = await listTemplates()
const template = templates.find(t => t.id === body.templateId)
if (!template) return Response.json({ error: 'Template introuvable' }, { status: 404 })
const templateBuffer = await readFile(getTemplateImagePath(template.filename))
const templateExt = template.filename.split('.').pop() ?? 'jpg'
const templateMime = templateExt === 'png' ? 'image/png' : 'image/jpeg'
const productBuffer = Buffer.from(body.productImageBase64, 'base64')
const form = new FormData()
form.append('model', 'gpt-image-1')
form.append('prompt', buildPrompt(body))
form.append('n', '1')
form.append('size', '1024x1024')
form.append('image[]', new Blob([templateBuffer], { type: templateMime }), `template.${templateExt}`)
form.append('image[]', new Blob([productBuffer], { type: 'image/png' }), 'product.png')
const openaiRes = await fetch('https://api.openai.com/v1/images/edits', {
method: 'POST',
headers: { Authorization: `Bearer ${apiKey}` },
body: form,
})
if (!openaiRes.ok) {
const err = await openaiRes.text()
return Response.json({ error: `OpenAI error: ${err}` }, { status: 502 })
}
const data = await openaiRes.json() as { data: Array<{ b64_json?: string }> }
const b64 = data.data?.[0]?.b64_json
if (!b64) return Response.json({ error: 'Pas de résultat OpenAI' }, { status: 502 })
return Response.json({ imageBase64: b64 })
}