198 lines
7.4 KiB
JavaScript
198 lines
7.4 KiB
JavaScript
/**
|
||
* 乐读派 AI 创作系统 — C 端接入完整示例
|
||
*
|
||
* 依赖安装:
|
||
* npm install crypto-js sockjs-client @stomp/stompjs
|
||
*
|
||
* 本示例演示完整的创作流程:
|
||
* 1. 校验额度
|
||
* 2. 获取画风列表
|
||
* 3. 发起 A1/A3 创作
|
||
* 4. WebSocket + HTTP 轮询双通道追踪进度
|
||
* 5. 获取创作结果
|
||
*/
|
||
|
||
import CreationApi from './CreationApi.js'
|
||
import CreationProgressTracker from './CreationProgressTracker.js'
|
||
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
// 配置(替换为实际值)
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
const CONFIG = {
|
||
serverUrl: 'https://your-server.com', // 替换为实际服务器地址
|
||
appKey: 'ORG001', // 机构 App Key
|
||
appSecret: 'your-app-secret', // 机构密钥(联系管理员获取)
|
||
phone: '13800138000' // 用户手机号
|
||
}
|
||
|
||
const api = new CreationApi(CONFIG.serverUrl, CONFIG.appKey, CONFIG.appSecret)
|
||
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
// 示例 1: A1 一句话创作(最简单的接入方式)
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
async function exampleA1Creation() {
|
||
console.log('=== A1 一句话创作 ===')
|
||
|
||
// Step 1: 校验额度
|
||
const validation = await api.validate(CONFIG.appKey, CONFIG.phone)
|
||
if (!validation.valid) {
|
||
console.error('额度不足:', validation.reason)
|
||
return
|
||
}
|
||
console.log('额度校验通过,剩余:', validation.remainQuota)
|
||
|
||
// Step 2: 获取画风列表
|
||
const styles = await api.getStyles()
|
||
console.log('可用画风:', styles.map(s => s.styleName).join(', '))
|
||
|
||
// Step 3: 发起创作
|
||
const result = await api.createBySentence({
|
||
orgId: CONFIG.appKey,
|
||
phone: CONFIG.phone,
|
||
sentence: '小恐龙学游泳',
|
||
style: 'style_cartoon',
|
||
enableVoice: false,
|
||
author: '小朋友',
|
||
age: 5
|
||
})
|
||
console.log('创作已提交,workId:', result.workId)
|
||
|
||
// Step 4: 追踪进度(WebSocket + HTTP 双通道)
|
||
const tracker = new CreationProgressTracker({
|
||
serverUrl: CONFIG.serverUrl,
|
||
orgId: CONFIG.appKey,
|
||
appKey: CONFIG.appKey,
|
||
appSecret: CONFIG.appSecret,
|
||
workId: result.workId,
|
||
|
||
onProgress: (progress, message) => {
|
||
// 更新 UI 进度条
|
||
console.log(`[${progress}%] ${message}`)
|
||
// updateProgressBar(progress)
|
||
// updateStatusText(message)
|
||
},
|
||
|
||
onComplete: (data) => {
|
||
if (data.status === 'COMPLETED') {
|
||
console.log('创作完成!')
|
||
console.log('标题:', data.title)
|
||
console.log('页数:', data.pageList.length)
|
||
console.log('耗时:', Math.round(data.durationMs / 1000), '秒')
|
||
|
||
// 展示绘本
|
||
data.pageList.forEach(page => {
|
||
console.log(` P${page.pageNum}: ${page.text}`)
|
||
console.log(` 图片: ${page.imageUrl}`)
|
||
if (page.audioUrl) console.log(` 音频: ${page.audioUrl}`)
|
||
})
|
||
} else {
|
||
console.error('创作失败:', data.failReason)
|
||
if (data.retryCount > 0) {
|
||
console.log(`(已自动重试 ${data.retryCount} 次)`)
|
||
}
|
||
}
|
||
},
|
||
|
||
onError: (err) => {
|
||
console.error('追踪异常:', err.message)
|
||
}
|
||
})
|
||
|
||
tracker.start()
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
// 示例 2: A3 图片故事创作(带角色引用)
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
async function exampleA3Creation() {
|
||
console.log('=== A3 图片故事创作 ===')
|
||
|
||
const result = await api.createByImage({
|
||
orgId: CONFIG.appKey,
|
||
phone: CONFIG.phone,
|
||
imageUrl: 'https://your-oss.com/upload/child-drawing.png',
|
||
storyHint: '小兔子去森林冒险',
|
||
style: 'style_watercolor',
|
||
enableVoice: true,
|
||
// 可选: 从 A5/A6 提取的角色引用
|
||
// heroCharId: 'char_123',
|
||
// characterRefs: [{ charId: 'char_123', imageUrl: 'https://...', name: '小兔子' }]
|
||
})
|
||
|
||
console.log('A3 创作已提交,workId:', result.workId)
|
||
|
||
// 使用 tracker 追踪进度(同示例1)
|
||
const tracker = new CreationProgressTracker({
|
||
serverUrl: CONFIG.serverUrl,
|
||
orgId: CONFIG.appKey,
|
||
appKey: CONFIG.appKey,
|
||
appSecret: CONFIG.appSecret,
|
||
workId: result.workId,
|
||
onProgress: (p, m) => console.log(`[${p}%] ${m}`),
|
||
onComplete: (data) => console.log('完成:', data.status, data.title)
|
||
})
|
||
tracker.start()
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
// 示例 3: 纯 B2 轮询(不使用 WebSocket,最简单接入)
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
async function exampleSimplePolling(workId) {
|
||
console.log('=== 纯 HTTP 轮询模式 ===')
|
||
|
||
const poll = async () => {
|
||
const data = await api.getWork(workId)
|
||
console.log(`[${data.progress}%] ${data.progressMessage}`)
|
||
|
||
if (data.status === 'COMPLETED') {
|
||
console.log('完成! 标题:', data.title, '页数:', data.pageList.length)
|
||
return
|
||
}
|
||
if (data.status === 'FAILED') {
|
||
console.error('失败:', data.failReason)
|
||
return
|
||
}
|
||
|
||
// 继续轮询
|
||
setTimeout(poll, 5000)
|
||
}
|
||
|
||
poll()
|
||
}
|
||
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
// 示例 4: A4 视频合成(基于已完成的作品)
|
||
// ═══════════════════════════════════════════════════════════════════
|
||
async function exampleVideoCreation(workId) {
|
||
console.log('=== A4 视频合成 ===')
|
||
|
||
const result = await api.createVideo({
|
||
orgId: CONFIG.appKey,
|
||
phone: CONFIG.phone,
|
||
workId: workId
|
||
})
|
||
|
||
console.log('视频合成已提交,轮询视频状态...')
|
||
|
||
const poll = async () => {
|
||
const data = await api.getWork(workId)
|
||
if (data.videoStatus === 'VIDEO_COMPLETED') {
|
||
console.log('视频完成:', data.videoUrl)
|
||
return
|
||
}
|
||
if (data.videoStatus === 'VIDEO_FAILED') {
|
||
console.error('视频失败:', data.failReason)
|
||
return
|
||
}
|
||
setTimeout(poll, 5000)
|
||
}
|
||
|
||
poll()
|
||
}
|
||
|
||
// 运行示例
|
||
// exampleA1Creation()
|
||
// exampleA3Creation()
|
||
// exampleSimplePolling('your-work-id')
|
||
// exampleVideoCreation('your-work-id')
|