Upload latest code and optimized prompts (v6)
This commit is contained in:
359
test-generate.js
Normal file
359
test-generate.js
Normal file
@@ -0,0 +1,359 @@
|
||||
/**
|
||||
* 测试脚本:使用素材图片生成电商图片
|
||||
* 运行方式: node test-generate.js
|
||||
*/
|
||||
|
||||
require('dotenv').config();
|
||||
const axios = require('axios');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
|
||||
|
||||
// 配置
|
||||
const SERVER_URL = 'http://localhost:3000';
|
||||
const OUTPUT_DIR = path.join(__dirname, 'output');
|
||||
const MATERIAL_DIR = path.join(__dirname, '素材/素材/已有的素材');
|
||||
|
||||
// R2客户端
|
||||
const r2Client = new S3Client({
|
||||
region: 'auto',
|
||||
endpoint: `https://${process.env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
|
||||
credentials: {
|
||||
accessKeyId: process.env.R2_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
|
||||
},
|
||||
forcePathStyle: true,
|
||||
});
|
||||
|
||||
/**
|
||||
* 上传图片到R2
|
||||
*/
|
||||
async function uploadToR2(filePath) {
|
||||
const fileName = `test-${Date.now()}-${path.basename(filePath)}`;
|
||||
const fileBuffer = fs.readFileSync(filePath);
|
||||
const contentType = filePath.endsWith('.png') ? 'image/png' : 'image/jpeg';
|
||||
|
||||
const command = new PutObjectCommand({
|
||||
Bucket: process.env.R2_BUCKET_NAME || 'ai-flow',
|
||||
Key: fileName,
|
||||
Body: fileBuffer,
|
||||
ContentType: contentType,
|
||||
});
|
||||
|
||||
await r2Client.send(command);
|
||||
|
||||
const publicUrl = process.env.R2_PUBLIC_DOMAIN
|
||||
? `${process.env.R2_PUBLIC_DOMAIN}/${fileName}`
|
||||
: `https://pub-${process.env.R2_ACCOUNT_ID}.r2.dev/${fileName}`;
|
||||
|
||||
console.log(` 上传成功: ${fileName}`);
|
||||
return publicUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载图片到本地
|
||||
*/
|
||||
async function downloadImage(url, outputPath) {
|
||||
try {
|
||||
const response = await axios.get(url, { responseType: 'arraybuffer', timeout: 60000 });
|
||||
fs.writeFileSync(outputPath, response.data);
|
||||
console.log(` 下载成功: ${path.basename(outputPath)}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(` 下载失败: ${error.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 主函数
|
||||
*/
|
||||
async function main() {
|
||||
console.log('\n========================================');
|
||||
console.log('Touchdog 电商图片生成测试');
|
||||
console.log('========================================\n');
|
||||
|
||||
// 确保输出目录存在
|
||||
if (!fs.existsSync(OUTPUT_DIR)) {
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
}
|
||||
|
||||
// 1. 获取素材图片
|
||||
console.log('📁 Step 1: 读取素材图片...');
|
||||
const materialFiles = fs.readdirSync(MATERIAL_DIR)
|
||||
.filter(f => /\.(jpg|jpeg|png)$/i.test(f))
|
||||
.slice(0, 3); // 取前3张作为参考
|
||||
|
||||
console.log(` 找到 ${materialFiles.length} 张素材图片`);
|
||||
|
||||
// 2. 上传素材到R2
|
||||
console.log('\n📤 Step 2: 上传素材到R2...');
|
||||
const refImageUrls = [];
|
||||
|
||||
for (const file of materialFiles) {
|
||||
try {
|
||||
const filePath = path.join(MATERIAL_DIR, file);
|
||||
const url = await uploadToR2(filePath);
|
||||
refImageUrls.push(url);
|
||||
} catch (error) {
|
||||
console.error(` 上传失败 ${file}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (refImageUrls.length === 0) {
|
||||
console.error('❌ 没有成功上传任何参考图片,退出');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(` 成功上传 ${refImageUrls.length} 张参考图`);
|
||||
|
||||
// 3. 构建SKU数据
|
||||
console.log('\n📝 Step 3: 构建SKU数据...');
|
||||
const sku = {
|
||||
sku_id: 'TD-EC-TEST-001',
|
||||
product_name: 'Cat Soft Cone Collar',
|
||||
product_name_cn: '伊丽莎白圈',
|
||||
brand: 'Touchdog',
|
||||
color: {
|
||||
name: 'Ice Blue',
|
||||
name_cn: '冰蓝色',
|
||||
series: 'Iridescent',
|
||||
hex: '#B0E0E6',
|
||||
edge_color: '#7FDBDB'
|
||||
},
|
||||
selling_points: [
|
||||
{
|
||||
key: 'lightweight',
|
||||
title_en: 'LIGHTER THAN AN EGG',
|
||||
title_cn: '极致轻盈',
|
||||
value: '65g',
|
||||
description_en: 'Cloud-light comfort at only 65g',
|
||||
visual_prompt: 'product shown next to an egg for size comparison'
|
||||
},
|
||||
{
|
||||
key: 'waterproof',
|
||||
title_en: 'WATERPROOF & EASY WIPE',
|
||||
title_cn: '防水易清洁',
|
||||
description_en: 'Waterproof PU fabric, stains wipe clean instantly',
|
||||
visual_prompt: 'water droplets beading on the surface'
|
||||
},
|
||||
{
|
||||
key: 'breathable',
|
||||
title_en: 'BREATHABLE COTTON LINING',
|
||||
title_cn: '舒适亲肤',
|
||||
description_en: 'Soft cotton inner layer, comfortable for extended wear',
|
||||
visual_prompt: 'close-up of soft cotton inner lining'
|
||||
},
|
||||
{
|
||||
key: 'adjustable',
|
||||
title_en: 'ADJUSTABLE STRAP',
|
||||
title_cn: '可调节',
|
||||
description_en: '3-second on/off, adjustable velcro',
|
||||
visual_prompt: 'velcro strap being adjusted'
|
||||
}
|
||||
],
|
||||
specs: {
|
||||
weight: '65g',
|
||||
depth_cm: '24.5',
|
||||
sizes: ['XS', 'S', 'M', 'L', 'XL'],
|
||||
materials: {
|
||||
outer: 'Durable Waterproof PU',
|
||||
inner: '95% Cotton + 5% Spandex'
|
||||
}
|
||||
},
|
||||
use_cases: [
|
||||
{ name_en: 'Postoperative Care', name_cn: '术后恢复' },
|
||||
{ name_en: 'Eye Drop Application', name_cn: '驱虫护理' },
|
||||
{ name_en: 'Nail Trimming', name_cn: '指甲修剪' },
|
||||
{ name_en: 'Grooming', name_cn: '美容护理' }
|
||||
],
|
||||
ref_images: refImageUrls
|
||||
};
|
||||
|
||||
console.log(' SKU数据准备完成');
|
||||
console.log(` 参考图: ${refImageUrls.length} 张`);
|
||||
|
||||
// 4. 调用生成API (只生成前3张测试)
|
||||
console.log('\n🎨 Step 4: 调用AI生图API...');
|
||||
console.log(' (为节省时间,仅生成3张测试图)\n');
|
||||
|
||||
// 直接调用图像生成API进行测试
|
||||
const testPrompts = [
|
||||
{
|
||||
id: 'Main_01',
|
||||
type: '场景首图+卖点摘要',
|
||||
prompt: `Professional Amazon main image for Touchdog Cat Soft Cone Collar, 1:1 square format.
|
||||
|
||||
COMPOSITION:
|
||||
- TOP 60%: A beautiful Ragdoll cat wearing the Ice Blue (#B0E0E6) soft cone collar in a cozy modern home interior with warm wood shelving. Natural soft lighting from window. Cat looks comfortable and relaxed. The cone collar is soft fabric with petal-like segments.
|
||||
|
||||
- BOTTOM 40%: Light blue (#B0E0E6) rounded banner with title "DESIGNED FOR COMFORTABLE RECOVERY" in navy blue text. Below: three small circular images showing:
|
||||
1. Product next to an egg showing 65g weight - "LIGHTER THAN AN EGG"
|
||||
2. Water droplets on surface - "WATERPROOF & EASY WIPE"
|
||||
3. Soft cotton lining detail - "BREATHABLE COTTON LINING"
|
||||
|
||||
PRODUCT REQUIREMENTS:
|
||||
- Soft cone collar with petal-like fabric segments, NOT rigid plastic
|
||||
- Color: Ice Blue (#B0E0E6) with teal edge binding (#7FDBDB)
|
||||
- Embroidered "TOUCHDOG®" logo visible on right petal (2-3 o'clock position)
|
||||
- Waterproof PU outer, soft cotton inner visible at edges
|
||||
|
||||
STYLE: Clean, professional Amazon listing photo. Warm home aesthetic. High-end pet product photography.
|
||||
|
||||
--ar 1:1`
|
||||
},
|
||||
{
|
||||
id: 'Main_02',
|
||||
type: '产品平铺+细节放大',
|
||||
prompt: `Professional Amazon product detail image for Touchdog Cat Soft Cone Collar, 1:1 square format.
|
||||
|
||||
COMPOSITION:
|
||||
- CENTER: Ice Blue (#B0E0E6) soft cone collar displayed flat from above on clean white background. Shows full petal-like segment structure.
|
||||
- Two circular detail callout bubbles with thin lines pointing to product:
|
||||
1. Left callout: "DURABLE WATERPROOF PU LAYER" - showing the smooth outer texture
|
||||
2. Right callout: "DOUBLE-LAYER COMFORT" - showing the soft ribbed edge binding in teal (#7FDBDB)
|
||||
|
||||
PRODUCT REQUIREMENTS:
|
||||
- Soft fabric cone with 8-10 petal segments radiating from center
|
||||
- Visible velcro closure strap
|
||||
- "TOUCHDOG®" embroidered logo on right side
|
||||
- Color: Ice Blue (#B0E0E6) main, teal binding
|
||||
|
||||
STYLE: Clean white background product photography. Professional Amazon listing style. Even studio lighting.
|
||||
|
||||
--ar 1:1`
|
||||
},
|
||||
{
|
||||
id: 'APlus_01',
|
||||
type: '品牌Banner',
|
||||
prompt: `Professional Amazon A+ brand banner image for Touchdog Cat Soft Cone Collar, landscape 970x600 format.
|
||||
|
||||
COMPOSITION:
|
||||
- FULL WIDTH: Warm modern living room scene with a beautiful white cat wearing the Ice Blue soft cone collar, standing gracefully on a light wood surface.
|
||||
- LEFT SIDE: Large stylized "TOUCHDOG" brand text in coral/pink color with playful font, paw print decorations
|
||||
- BELOW: "CAT SOFT CONE COLLAR" product name text
|
||||
|
||||
PRODUCT REQUIREMENTS:
|
||||
- Cat wearing Ice Blue (#B0E0E6) soft cone collar
|
||||
- Petal-like fabric segments visible
|
||||
- Collar looks soft and comfortable, not rigid
|
||||
|
||||
ENVIRONMENT:
|
||||
- Cozy modern home interior
|
||||
- Soft natural lighting
|
||||
- Warm neutral tones (beige, cream, light wood)
|
||||
- Professional lifestyle photography feel
|
||||
|
||||
BRAND ELEMENTS:
|
||||
- Touchdog logo with heart-shaped dog icon in red
|
||||
- "wow pretty" tagline
|
||||
|
||||
--ar 3:2`
|
||||
}
|
||||
];
|
||||
|
||||
const results = [];
|
||||
|
||||
for (const testPrompt of testPrompts) {
|
||||
console.log(` 生成 ${testPrompt.id}: ${testPrompt.type}...`);
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
model: 'gemini-3-pro-image-preview',
|
||||
prompt: testPrompt.prompt,
|
||||
n: 1,
|
||||
size: '1K',
|
||||
aspect_ratio: testPrompt.id.startsWith('APlus') ? '3:2' : '1:1',
|
||||
image_urls: refImageUrls
|
||||
};
|
||||
|
||||
const response = await axios.post(
|
||||
'https://api2img.shubiaobiao.com/v1/images/generations',
|
||||
payload,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${process.env.API_KEY}`
|
||||
},
|
||||
timeout: 180000
|
||||
}
|
||||
);
|
||||
|
||||
// 处理响应 - 可能是URL或base64
|
||||
const imageData = response.data.data?.[0];
|
||||
const outputPath = path.join(OUTPUT_DIR, `${sku.sku_id}-${testPrompt.id}.jpg`);
|
||||
|
||||
if (imageData?.b64_json) {
|
||||
// Base64格式 - 直接保存
|
||||
const imageBuffer = Buffer.from(imageData.b64_json, 'base64');
|
||||
fs.writeFileSync(outputPath, imageBuffer);
|
||||
console.log(` 保存成功: ${path.basename(outputPath)}`);
|
||||
|
||||
results.push({
|
||||
id: testPrompt.id,
|
||||
type: testPrompt.type,
|
||||
localPath: outputPath,
|
||||
status: 'success'
|
||||
});
|
||||
|
||||
console.log(` ✓ ${testPrompt.id} 生成成功`);
|
||||
} else if (imageData?.url) {
|
||||
// URL格式 - 下载保存
|
||||
await downloadImage(imageData.url, outputPath);
|
||||
|
||||
results.push({
|
||||
id: testPrompt.id,
|
||||
type: testPrompt.type,
|
||||
url: imageData.url,
|
||||
localPath: outputPath,
|
||||
status: 'success'
|
||||
});
|
||||
|
||||
console.log(` ✓ ${testPrompt.id} 生成成功`);
|
||||
} else {
|
||||
throw new Error('No image data in response');
|
||||
}
|
||||
|
||||
// 延迟避免限流
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
|
||||
} catch (error) {
|
||||
console.error(` ✗ ${testPrompt.id} 生成失败: ${error.message}`);
|
||||
results.push({
|
||||
id: testPrompt.id,
|
||||
type: testPrompt.type,
|
||||
status: 'failed',
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 输出结果
|
||||
console.log('\n========================================');
|
||||
console.log('生成结果汇总');
|
||||
console.log('========================================');
|
||||
|
||||
const successCount = results.filter(r => r.status === 'success').length;
|
||||
console.log(`\n成功: ${successCount}/${results.length}`);
|
||||
|
||||
results.forEach(r => {
|
||||
const status = r.status === 'success' ? '✓' : '✗';
|
||||
console.log(` ${status} ${r.id} - ${r.type}`);
|
||||
if (r.localPath) {
|
||||
console.log(` 保存位置: ${r.localPath}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(`\n📁 输出目录: ${OUTPUT_DIR}`);
|
||||
console.log('\n========================================\n');
|
||||
|
||||
// 保存结果JSON
|
||||
fs.writeFileSync(
|
||||
path.join(OUTPUT_DIR, 'generation-results.json'),
|
||||
JSON.stringify({ sku, results }, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
// 运行
|
||||
main().catch(console.error);
|
||||
|
||||
Reference in New Issue
Block a user