Files
amz-pic-flow/test-generate.js

360 lines
11 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 测试脚本:使用素材图片生成电商图片
* 运行方式: 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);