基于 Next.js + 火山引擎 AI 的电商素材智能生成工具实战——字节跳动前端训练营成果

一、项目背景

本项目利用 火山引擎豆包大模型的 AI 能力,打造一站式电商素材生成工具:

需要使用爬墙工具访问网站:

在线体验:https://e-commerce-ai-tool.vercel.app

GitHub 仓库:https://github.com/niuyiduo/e-commerce-ai-tool

声明:使用的是试用的免费模型,已经将API停用,仅用于记录和学习使用。

二、核心功能全景图

2.1 功能架构

│ 📸 图片处理模块 │ 🤖 AI 生成模块 │ 🎬 视频生成模块 │

│ ├── 拖拽上传 │ ├── 6模型切换 │ ├── 多图合成 │

│ ├── 智能尺寸 │ ├── 文案生成 │ ├── 转场特效 │

│ └── 图片预览 │ ├── 智能装饰 │ ├── 虚拟人讲解 │

│ │ └── 边框动画 │ └── 语音配音 │

2.2 技术亮点速览

|------|----------------|------------------------------|
| 特性 | 实现方案 | 亮点 |
| 图片装饰 | Canvas API | 100+ 贴纸 + 4 种动画边框 |
| 视频生成 | MediaRecorder | 纯前端合成,无需后端 |
| 虚拟人 | Three.js + VRM | 52 种表情 + 15 种口型 |
| 语言合成 | 火山引擎 TTS | 男女双声 + 真实时长同步 |
| AI对话 | 火山引擎 6 模型 | Pro/Lite/Vision/Thinking 全覆盖 |
[技术亮点]

三、技术架构深度解析

3.1 整体技术栈

typescript

// 核心技术选型

const techStack = {

前端框架: 'Next.js 14 (App Router)',

开发语言: 'TypeScript 5.x',

样式方案: 'Tailwind CSS + 抖音黑色主题',

AI 服务: '火山引擎豆包大模型(6模型)',

3D 渲染: 'Three.js + @pixiv/three-vrm',

音视频: 'Canvas + MediaRecorder + Web Audio API',

部署平台: 'Vercel Edge Network',

数据库: 'MySQL(持久化存储)'

};

3.2 项目目录结构

e-commerce-ai-tool/

├── src/

│ ├── app/

│ │ ├── api/

│ │ │ ├── chat/route.ts # AI 对话接口

│ │ │ ├── tts/route.ts # 语音合成接口

│ │ │ └── logs/route.ts # 数据持久化接口

│ │ ├── page.tsx # 主页面(核心交互)

│ │ └── layout.tsx # 根布局

│ ├── lib/

│ │ ├── ai/volcengine.ts # 火山引擎 AI 调用

│ │ ├── canvas/

│ │ │ └── imageGenerator.ts # 图片生成与装饰

│ │ ├── video/

│ │ │ └── videoGenerator.ts # 视频生成核心

│ │ └── db.ts # MySQL 数据库连接

│ └── types/global.d.ts # TypeScript 类型定义

├── public/avatars/ # VRM 虚拟形象模型

└── database/schema.sql # 数据库建表语句

四、核心功能实现详解

4.1 AI 多模型切换架构

项目支持 6 个豆包模型动态切换,实现不同场景的精准匹配:

typescript

// 模型配置定义

const availableModels = [

{

id: 'Doubao-1.5-pro-32k',

name: 'Doubao-1.5-pro-32k',

description: '高性能版本,适合复杂任务',

endpoint: process.env.VOLCENGINE_ENDPOINT_PRO_32K

},

{

id: 'Doubao-1.5-pro-4k',

name: 'Doubao-1.5-pro-4k',

description: '标准版本,快速响应',

endpoint: process.env.VOLCENGINE_ENDPOINT_PRO_4K

},

{

id: 'Doubao-1.5-vision-pro',

name: 'Doubao-vision',

description: '多模态模型,支持图文理解',

endpoint: process.env.VOLCENGINE_ENDPOINT_VISION

},

{

id: 'Doubao-1.5-vision-thinking-pro',

name: 'Doubao-thinking-vision',

description: '思维链多模态,更强推理能力',

endpoint: process.env.VOLCENGINE_ENDPOINT_THINKING_VISION

}

];

// 动态端点映射

const getEndpointForModel = (modelId: string): string => {

const endpointMap: Record<string, string> = {

'Doubao-1.5-pro-32k': process.env.VOLCENGINE_ENDPOINT_PRO_32K!,

'Doubao-1.5-pro-4k': process.env.VOLCENGINE_ENDPOINT_PRO_4K!,

'Doubao-1.5-vision-pro': process.env.VOLCENGINE_ENDPOINT_VISION!,

'Doubao-1.5-vision-thinking-pro': process.env.VOLCENGINE_ENDPOINT_THINKING_VISION!,

};

return endpointMap[modelId] || process.env.VOLCENGINE_ENDPOINT_ID!;

};

模型选择策略:

文案生成:Pro-32k(复杂)/ Lite-4k(快速测试)

图文理解:Vision(多模态分析)

深度推理:Thinking-Vision(思维链推理)

4.2 智能图片装饰系统

4.2.1 普通装饰模式

使用 Canvas API 实现 100+ 装饰元素随机分布:

typescript

// 装饰元素库

const decorativeElements = {

badges: ['🔥 热卖', '✨ 新品', '⚡ 特价', '🎁 赠品'],

stickers: ['⭐', '❤️', '💎', '🎀', '✨', '💫', '🌟', ...], // 100+ emoji

effects: ['光晕', '阴影', '边框']

};

// 随机分布算法

const generateDecorativeImage = async (

imageSrc: string,

productInfo: ProductInfo

): Promise<string> => {

const canvas = document.createElement('canvas');

const ctx = canvas.getContext('2d')!;

// 1. 绘制原图

const img = await loadImage(imageSrc);

canvas.width = img.width;

canvas.height = img.height;

ctx.drawImage(img, 0, 0);

// 2. 添加促销徽章(随机位置)

const badge = decorativeElements.badges[Math.floor(Math.random() * 4)];

drawBadge(ctx, badge, { x: 30, y: 30 });

// 3. 添加装饰贴纸(随机分布)

for (let i = 0; i < 15; i++) {

const sticker = decorativeElements.stickers[

Math.floor(Math.random() * decorativeElements.stickers.length)

];

const x = Math.random() * (canvas.width - 50);

const y = Math.random() * (canvas.height - 50);

drawSticker(ctx, sticker, { x, y }, Math.random() * 30 + 20);

}

// 4. 添加水印

addWatermark(ctx, '抖音电商前端训练营', canvas.width, canvas.height);

return canvas.toDataURL('image/png');

};

4.2.2 高级定制模式(Vision 模型)

AI 智能分析商品图片,生成个性化装饰:

typescript

// AI 分析提示词

const ANALYSIS_PROMPT = `请分析这张商品图片,提取以下信息并以JSON格式返回:

{

"商品名": "商品名称",

"产地": "生产地",

"卖点": "核心卖点(15字以内)",

"说明": "详细说明(50字以内)"

}`;

// 高级装饰生成流程

const generateSmartDecorativeImage = async (

imageSrc: string,

model: string,

borderStyle: BorderStyle

): Promise<string> => {

// 1. 调用 Vision 模型分析图片

const analysis = await analyzeImageWithAI(imageSrc, model);

const productInfo = JSON.parse(analysis);

// 2. 生成装饰框

const canvas = document.createElement('canvas');

const ctx = canvas.getContext('2d')!;

// 3. 绘制动态边框(4种风格)

drawBorder(ctx, borderStyle, canvas.width, canvas.height);

// 4. 添加商品信息文字

drawProductInfo(ctx, productInfo);

// 5. 添加水印

addWatermark(ctx, '抖音电商前端训练营', canvas.width, canvas.height);

return canvas.toDataURL('image/png');

};

4.2.3 动画边框实现

纯 Canvas 绘制 + CSS 动画实现:

typescript

// 边框绘制函数

type BorderStyle = 'simple' | 'guochao' | 'gradient' | 'luxury';

const drawBorder = (

ctx: CanvasRenderingContext2D,

style: BorderStyle,

width: number,

height: number

) => {

const borderWidth = 25;

switch (style) {

case 'simple':

// 简约边框:白灰双线 + 缩放动画

ctx.strokeStyle = '#E5E7EB';

ctx.lineWidth = borderWidth;

ctx.strokeRect(0, 0, width, height);

ctx.strokeStyle = '#FFFFFF';

ctx.lineWidth = borderWidth / 2;

ctx.strokeRect(borderWidth/4, borderWidth/4,

width - borderWidth/2, height - borderWidth/2);

break;

case 'guochao':

// 国潮边框:红金渐变 + 四角菱形 + 流动动画

const gradient = ctx.createLinearGradient(0, 0, width, 0);

gradient.addColorStop(0, '#DC2626');

gradient.addColorStop(0.5, '#F59E0B');

gradient.addColorStop(1, '#DC2626');

ctx.strokeStyle = gradient;

ctx.lineWidth = borderWidth;

ctx.strokeRect(0, 0, width, height);

// 四角装饰

drawCornerDecorations(ctx, 'diamond', width, height);

break;

case 'gradient':

// 渐变边框:紫粉蓝渐变 + 彩虹扩散动画

const rainbowGradient = ctx.createConicGradient(0, width/2, height/2);

rainbowGradient.addColorStop(0, '#8B5CF6');

rainbowGradient.addColorStop(0.33, '#EC4899');

rainbowGradient.addColorStop(0.66, '#3B82F6');

rainbowGradient.addColorStop(1, '#8B5CF6');

ctx.strokeStyle = rainbowGradient;

ctx.lineWidth = borderWidth;

ctx.strokeRect(0, 0, width, height);

break;

case 'luxury':

// 豪华边框:三层金色 + 宝石装饰 + 光带扫过动画

for (let i = 0; i < 3; i++) {

ctx.strokeStyle = `rgba(251, 191, 36, ${0.3 + i * 0.3})`;

ctx.lineWidth = borderWidth - i * 5;

ctx.strokeRect(i * 5, i * 5,

width - i * 10, height - i * 10);

}

drawCornerDecorations(ctx, 'gem', width, height);

break;

}

};

4.3 纯前端视频生成方案

4.3.1 核心技术组合

视频生成 = Canvas 绘制 + MediaRecorder 录制 + Web Audio API 混音

typescript

// 视频生成主函数

const generateVideo = async (

images: string[],

duration: number,

transition: 'fade' | 'slide' | 'none',

captions: string[],

enableVoice: boolean,

voiceType: 'male' | 'female',

enableAvatar: boolean

): Promise<string> => {

// 1. 创建 Canvas

const canvas = document.createElement('canvas');

const ctx = canvas.getContext('2d')!;

// 2. 智能尺寸适配

const isAllPortrait = images.every(img => isPortrait(img));

canvas.width = isAllPortrait ? 720 : 1280;

canvas.height = isAllPortrait ? 1280 : 720;

// 3. 获取音频(如启用配音)

let audioBuffer: AudioBuffer | null = null;

if (enableVoice) {

const ttsAudio = await synthesizeSpeech(captions.join(' '), voiceType);

audioBuffer = await decodeAudioData(ttsAudio);

}

// 4. 设置 MediaRecorder

const stream = canvas.captureStream(30); // 30fps

const mediaRecorder = new MediaRecorder(stream, {

mimeType: 'video/webm;codecs=vp9'

});

// 5. 录制视频帧

const chunks: Blob[] = [];

mediaRecorder.ondataavailable = (e) => chunks.push(e.data);

return new Promise((resolve) => {

mediaRecorder.onstop = () => {

const videoBlob = new Blob(chunks, { type: 'video/webm' });

// 6. 音视频合成

if (audioBuffer) {

muxAudioVideo(videoBlob, audioBuffer).then(resolve);

} else {

resolve(URL.createObjectURL(videoBlob));

}

};

mediaRecorder.start();

renderFrames(ctx, images, duration, transition, captions, enableAvatar);

setTimeout(() => mediaRecorder.stop(), duration * 1000);

});

};

4.3.2 转场效果实现

typescript

// 淡入淡出转场

const renderFadeTransition = (

ctx: CanvasRenderingContext2D,

img1: HTMLImageElement,

img2: HTMLImageElement,

progress: number // 0-1

) => {

ctx.globalAlpha = 1 - progress;

ctx.drawImage(img1, 0, 0, canvas.width, canvas.height);

ctx.globalAlpha = progress;

ctx.drawImage(img2, 0, 0, canvas.width, canvas.height);

ctx.globalAlpha = 1;

};

// 滑动转场

const renderSlideTransition = (

ctx: CanvasRenderingContext2D,

img1: HTMLImageElement,

img2: HTMLImageElement,

progress: number,

direction: 'left' | 'right' = 'right'

) => {

const offset = progress * canvas.width * (direction === 'right' ? 1 : -1);

ctx.drawImage(img1, offset, 0, canvas.width, canvas.height);

ctx.drawImage(img2,

offset + (direction === 'right' ? -canvas.width : canvas.width),

0, canvas.width, canvas.height

);

};

4.4 虚拟人讲解系统

4.4.1 VRoid 顶级形象渲染

使用 Three.js + @pixiv/three-vrm 实现专业级 3D 虚拟人:

typescript

// VRoid 形象管理器

class VRoidAvatarManager {

private scene: THREE.Scene;

private camera: THREE.PerspectiveCamera;

private renderer: THREE.WebGLRenderer;

private vrm: VRM | null = null;

private expressionManager: VRMExpressionManager | null = null;

// 52 种表情映射

private expressions = [

'happy', 'angry', 'sad', 'relaxed', 'surprised',

'blink', 'blinkLeft', 'blinkRight', ... // 52种

];

// 15 种口型映射(Viseme)

private visemes = ['aa', 'ih', 'ou', 'ee', 'oh', ...]; // 15种

async loadVRM(url: string): Promise<void> {

const loader = new GLTFLoader();

const gltf = await loader.loadAsync(url);

// 生成 VRM 实例

this.vrm = await VRM.from(gltf);

this.expressionManager = this.vrm.expressionManager;

// 脸部特写模式:摄像机 Z 轴 -1.2

this.camera.position.set(0, 1.4, -1.2);

this.camera.lookAt(0, 1.4, 0);

// 静止姿态优化

this.vrm.humanoid.getNormalizedBoneNode('hips')!.rotation.set(0, 0, 0);

}

// 设置表情

setExpression(expressionName: string, weight: number = 1.0): void {

if (this.expressionManager) {

this.expressionManager.setValue(expressionName, weight);

}

}

// 口型同步

setViseme(visemeName: string, weight: number): void {

if (this.expressionManager) {

this.expressionManager.setValue(visemeName, weight);

}

}

// 动画循环

animate(audioDuration: number): void {

const startTime = performance.now();

const loop = () => {

const elapsed = (performance.now() - startTime) / 1000;

if (elapsed < audioDuration) {

// 配音中:循环切换口型

const visemeIndex = Math.floor(elapsed * 10) % this.visemes.length;

this.setViseme(this.visemes[visemeIndex], 1.0);

// 随机眨眼

if (Math.random() < 0.02) {

this.setExpression('blink', 1.0);

setTimeout(() => this.setExpression('blink', 0), 150);

}

requestAnimationFrame(loop);

} else {

// 配音结束:恢复微笑

this.setExpression('happy', 0.5);

}

};

loop();

}

}

4.4.2 智能性别匹配

根据 TTS 音色自动选择对应形象:

typescript

// 音色与形象映射

const avatarMapping = {

'BV001_streaming': { // 女声

vroid: '/avatars/female/红裙女孩.vrm',

cute: '/avatars/female/中国风可爱女娃娃.vrm'

},

'BV002_streaming': { // 男声

vroid: '/avatars/male/西装男生.vrm',

cute: '/avatars/male/男生Q版.vrm'

}

};

// 自动选择形象

const selectAvatarByVoice = (voiceType: string, avatarStyle: 'vroid' | 'cute') => {

return avatarMapping[voiceType]?.[avatarStyle] || avatarMapping['BV001_streaming'].vroid;

};

五、性能优化策略

5.1 智能超时机制

不同模型设置不同超时时间,平衡体验与资源:

typescript

// 模型超时配置

const modelTimeoutConfig: Record<string, number> = {

'Doubao-1.5-vision-thinking-pro': 60000, // Thinking: 60s

'Doubao-1.5-vision-pro': 30000, // Vision: 30s

'default': 30000 // 其他: 30s

};

// 带超时的 fetch 封装

const fetchWithTimeout = async (

url: string,

options: RequestInit,

model: string

): Promise<Response> => {

const timeout = modelTimeoutConfig[model] || modelTimeoutConfig.default;

const controller = new AbortController();

const timeoutId = setTimeout(() => controller.abort(), timeout);

try {

const response = await fetch(url, {

...options,

signal: controller.signal

});

clearTimeout(timeoutId);

return response;

} catch (error) {

clearTimeout(timeoutId);

if (error.name === 'AbortError') {

throw new Error(`请求超时(${timeout/1000}秒),请重试或切换模型`);

}

throw error;

}

};

5.2 Token 优化

限制对话历史,减少 Token 消耗:

typescript

// 对话历史管理

const MAX_HISTORY_ROUNDS = 6; // 保留最近 6 轮对话

const optimizeMessages = (messages: Message[]): Message[] => {

if (messages.length <= MAX_HISTORY_ROUNDS * 2) return messages;

// 保留系统提示 + 最近 N 轮对话

const systemMessages = messages.filter(m => m.role === 'system');

const conversationMessages = messages.filter(m => m.role !== 'system');

const recentMessages = conversationMessages.slice(-MAX_HISTORY_ROUNDS * 2);

return [...systemMessages, ...recentMessages];

};

// 效果:Token 消耗减少 89%

5.3 图片尺寸标准化

统一图片尺寸,确保生成质量:

typescript

// 智能尺寸标准化

const standardizeImageSize = (

img: HTMLImageElement

): { width: number; height: number } => {

const targetSize = 1200;

const isPortrait = img.height > img.width;

if (isPortrait) {

// 竖版:固定高度 1200

return {

width: Math.round(img.width * (targetSize / img.height)),

height: targetSize

};

} else {

// 横版:固定宽度 1200

return {

width: targetSize,

height: Math.round(img.height * (targetSize / img.width))

};

}

};

六、CI/CD 自动化部署

6.1 Vercel 部署流程

.github/workflows/deploy.yml(Vercel 自动处理)

部署流程:

  1. 开发者推送代码到 GitHub

  2. Vercel Webhook 检测更新

  3. 自动执行 npm install

  4. 自动执行 npm run build

  5. 部署到 Edge Network

  6. 全球 CDN 自动刷新

6.2 环境变量配置

.env.local 配置示例

AI 服务配置

VOLCENGINE_API_KEY=your_api_key

VOLCENGINE_ENDPOINT_ID=your_endpoint_id

VOLCENGINE_ENDPOINT_PRO_32K=your_pro_32k_endpoint

VOLCENGINE_ENDPOINT_VISION=your_vision_endpoint

VOLCENGINE_ENDPOINT_THINKING_VISION=your_thinking_endpoint

TTS 服务配置

VOLCENGINE_TTS_APP_ID=your_tts_app_id

VOLCENGINE_TTS_TOKEN=your_tts_token

数据库配置

DB_HOST=localhost

DB_PORT=3306

DB_USER=root

DB_PASSWORD=your_password

DB_NAME=e-commerce-ai-tool

七、项目成果与数据

展示视频

说明:最终效果还是水平不够,一是模型不太行;二是开发成本高昂;三是技术能力有限;四是开发周期较短;四:模型有冗余的地方,功能不完善;五:整体呈现效果不够美观,使用欲望较低。

八、总结与心得

8.1 技术收获

  1. AI 工程化:从 API 调用到多模型管理,理解大模型应用架构

  2. 前端多媒体:Canvas、MediaRecorder、Web Audio API 的深度实践

  3. 3D 渲染:Three.js + VRM 虚拟人技术的完整掌握

  4. 性能优化:Token 管理、超时控制、资源优化的实战经验

8.2 项目亮点

纯前端方案:视频生成无需后端,降低部署成本

多模型架构:6 个 AI 模型灵活切换,覆盖全场景

虚拟人技术:52 种表情 + 15 种口型的专业级实现

完整 CI/CD:GitHub + Vercel 自动化部署

8.3 不足之处

除了展示说明中的内容,在呈现过程中本地运行可以正常测试,在在线网站是经常出现超时无法响应现象,这是最大的痛点,到底还是不能很好的使用算法。

相关推荐
xingyuzhisuan2 小时前
租用GPU服务器进行深度学习课程教学的实验环境搭建
运维·人工智能·深度学习·gpu算力
yu85939582 小时前
神经网络遗传算法函数极值寻优(非线性函数极值)
人工智能·深度学习·神经网络
乔江seven2 小时前
【李沐 | 动手学深度学习】12 使用块的网络VGG
人工智能·深度学习·卷积神经网络·vgg网络
haina20192 小时前
《品牌观察》专访海纳AI:引领AI面试测评新时代
人工智能·面试·职场和发展
云烟成雨TD3 小时前
Spring AI Alibaba 1.x 系列【22】Agent 并行工具执行与超时 / 协作式取消实战
java·人工智能·spring
阿里云大数据AI技术3 小时前
让 AI 帮你写大数据AI开发代码:MaxFrame Coding Skill 正式发布
人工智能·agent
麦哲思科技任甲林3 小时前
大懒人AI结对工作模式——驾驭AI编程的进阶指南
人工智能·ai编程·结对编程·工作模式·ai赋能
Raink老师3 小时前
【AI面试临阵磨枪】什么是 MCP(Model Control Protocol)、A2A(Agent-to-Agent)协议?
人工智能·面试·职场和发展·ai 面试