视频(Video)
视频API使用示例和最佳实践
本文档提供了88API 视频生成API的完整使用示例和最佳实践指南。
完整使用流程示例
1. 88API格式完整流程
// 1. 生成视频
async function generateVideoWith88API() {
const response = await fetch(
'https://88api.ai/v1/video/generations',
{
method: 'POST',
headers: {
Authorization: 'Bearer sk-xxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'kling-v1',
prompt: '一个穿着宇航服的宇航员在月球上行走, 高品质, 电影级',
size: '1920x1080',
duration: 5,
metadata: {
seed: 20231234,
negative_prompt: '模糊, 低质量',
},
}),
}
);
const result = await response.json();
return result.task_id;
}
// 2. 轮询查询状态
async function pollVideoStatus(taskId, maxAttempts = 30) {
const baseUrl = 'https://88api.ai';
const headers = {
Authorization: 'Bearer sk-xxxx',
'Content-Type': 'application/json',
};
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
const response = await fetch(
`${baseUrl}/v1/video/generations/${taskId}`,
{
headers,
}
);
const result = await response.json();
if (result.status === 'succeeded') {
return result;
} else if (result.status === 'failed') {
throw new Error(`视频生成失败: ${result.error?.message || '未知错误'}`);
}
// 等待后重试
const delay = attempt < 6 ? 5000 : attempt < 12 ? 10000 : 30000;
await new Promise((resolve) => setTimeout(resolve, delay));
} catch (error) {
console.error(`第 ${attempt + 1} 次尝试失败:`, error);
if (attempt === maxAttempts - 1) {
throw error;
}
}
}
throw new Error('达到最大轮询次数');
}
// 3. 下载视频
async function downloadVideo(taskId) {
const response = await fetch(
`https://88api.ai/v1/videos/${taskId}/content`,
{
headers: {
Authorization: 'Bearer sk-xxxx',
},
}
);
if (!response.ok) {
throw new Error(`下载失败: ${response.statusText}`);
}
const blob = await response.blob();
return blob;
}
// 完整流程示例
async function completeVideoWorkflow() {
try {
// 生成视频
console.log('正在生成视频...');
const taskId = await generateVideoWith88API();
console.log('任务ID:', taskId);
// 轮询状态
console.log('正在查询生成状态...');
const result = await pollVideoStatus(taskId);
console.log('视频生成完成:', result.url);
// 下载视频
console.log('正在下载视频...');
const videoBlob = await downloadVideo(taskId);
// 保存视频
const url = URL.createObjectURL(videoBlob);
const a = document.createElement('a');
a.href = url;
a.download = `video_${taskId}.mp4`;
a.click();
URL.revokeObjectURL(url);
console.log('视频下载完成');
} catch (error) {
console.error('流程失败:', error);
}
}2. OpenAI兼容格式完整流程
// 1. 生成视频 (OpenAI格式)
async function generateVideoWithOpenAIFormat() {
const response = await fetch('https://88api.ai/v1/videos', {
method: 'POST',
headers: {
Authorization: 'Bearer sk-xxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'sora-2',
prompt: '一个穿着宇航服的宇航员在月球上行走, 高品质, 电影级',
seconds: '5',
size: '1920x1080',
}),
});
const result = await response.json();
return result.id;
}
// 2. 查询状态 (OpenAI格式)
async function pollVideoStatusOpenAI(videoId, maxAttempts = 30) {
const baseUrl = 'https://88api.ai';
const headers = {
Authorization: 'Bearer sk-xxxx',
'Content-Type': 'application/json',
};
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
const response = await fetch(`${baseUrl}/v1/videos/${videoId}`, {
headers,
});
const result = await response.json();
if (result.status === 'succeeded') {
return result;
} else if (result.status === 'failed') {
throw new Error(`视频生成失败: ${result.error?.message || '未知错误'}`);
}
// 等待后重试
const delay = attempt < 6 ? 5000 : attempt < 12 ? 10000 : 30000;
await new Promise((resolve) => setTimeout(resolve, delay));
} catch (error) {
console.error(`第 ${attempt + 1} 次尝试失败:`, error);
if (attempt === maxAttempts - 1) {
throw error;
}
}
}
throw new Error('达到最大轮询次数');
}不同模型的详细示例
可灵AI (Kling) 示例
# 文生视频
curl -X POST https://88api.ai/v1/video/generations \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-v1",
"prompt": "一只橘猫在阳光下打盹,毛发蓬松,表情安详",
"duration": 5,
"metadata": {
"seed": 12345,
"negative_prompt": "模糊, 扭曲",
"cfg_scale": 0.8
}
}'
# 图生视频
curl -X POST https://88api.ai/v1/video/generations \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "kling-v2-master",
"image": "https://example.com/cat.jpg",
"prompt": "猫咪慢慢睁开眼睛,伸懒腰",
"duration": 3,
"metadata": {
"seed": 54321,
"negative_prompt": "快速动作",
"camera_control": {
"type": "simple",
"config": {
"horizontal": 1.0,
"vertical": 0,
"zoom": 0.5
}
}
}
}'即梦 (Jimeng) 示例
# 文生视频
curl -X POST https://88api.ai/v1/video/generations \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "jimeng_vgfm_t2v_l20",
"prompt": "海浪拍打着礁石,溅起白色的浪花",
"metadata": {
"req_key": "jimeng_vgfm_t2v_l20",
"aspect_ratio": "16:9",
"duration": 5
}
}'
# 图生视频
curl -X POST https://88api.ai/v1/video/generations \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "jimeng_vgfm_i2v_l20",
"image": "https://example.com/landscape.jpg",
"prompt": "云朵缓缓飘过天空",
"metadata": {
"req_key": "jimeng_vgfm_i2v_l20",
"image_urls": ["https://example.com/landscape.jpg"],
"aspect_ratio": "16:9"
}
}'Vidu 示例
curl -X POST https://88api.ai/v1/video/generations \
-H "Authorization: Bearer sk-xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "viduq1",
"prompt": "未来城市的夜景,霓虹灯闪烁",
"size": "1920x1080",
"duration": 5,
"metadata": {
"resolution": "1080p",
"movement_amplitude": "medium",
"bgm": true,
"seed": 0,
"callback_url": "https://your-callback-url.com/webhook"
}
}'错误处理最佳实践
1. 完整的错误处理示例
class VideoAPIClient {
constructor(apiKey, baseUrl) {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async generateVideo(params, format = 'newapi') {
try {
const endpoint =
format === 'openai' ? '/v1/videos' : '/v1/video/generations';
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json();
throw new VideoAPIError(response.status, errorData);
}
return await response.json();
} catch (error) {
if (error instanceof VideoAPIError) {
throw error;
}
throw new VideoAPIError(0, { message: error.message });
}
}
async pollStatus(taskId, format = 'newapi', options = {}) {
const { maxAttempts = 30, initialDelay = 2000, maxDelay = 30000 } = options;
let delay = initialDelay;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
const endpoint =
format === 'openai'
? `/v1/videos/${taskId}`
: `/v1/video/generations/${taskId}`;
const response = await fetch(`${this.baseUrl}${endpoint}`, {
headers: {
Authorization: `Bearer ${this.apiKey}`,
'Content-Type': 'application/json',
},
});
if (!response.ok) {
const errorData = await response.json();
throw new VideoAPIError(response.status, errorData);
}
const result = await response.json();
if (result.status === 'succeeded') {
return result;
} else if (result.status === 'failed') {
throw new VideoAPIError(400, {
message: result.error?.message || '视频生成失败',
});
}
// 等待后重试
await this.sleep(delay);
delay = Math.min(delay * 1.5, maxDelay);
} catch (error) {
if (error instanceof VideoAPIError) {
throw error;
}
console.error(`第 ${attempt + 1} 次轮询失败:`, error);
if (attempt === maxAttempts - 1) {
throw new VideoAPIError(0, { message: '轮询超时' });
}
}
}
}
async downloadVideo(taskId) {
try {
const response = await fetch(
`${this.baseUrl}/v1/videos/${taskId}/content`,
{
headers: {
Authorization: `Bearer ${this.apiKey}`,
},
}
);
if (!response.ok) {
const errorData = await response.json();
throw new VideoAPIError(response.status, errorData);
}
return await response.blob();
} catch (error) {
if (error instanceof VideoAPIError) {
throw error;
}
throw new VideoAPIError(0, { message: error.message });
}
}
sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
}
class VideoAPIError extends Error {
constructor(status, data) {
super(data.message || '未知错误');
this.status = status;
this.data = data;
this.name = 'VideoAPIError';
}
}
// 使用示例
async function exampleUsage() {
const client = new VideoAPIClient('sk-xxxx', 'https://88api.ai');
try {
// 生成视频
const result = await client.generateVideo({
model: 'kling-v1',
prompt: '一只可爱的小狗在花园里玩耍',
duration: 5,
});
console.log('任务创建成功:', result.task_id);
// 轮询状态
const status = await client.pollStatus(result.task_id, 'newapi', {
maxAttempts: 20,
initialDelay: 3000,
});
console.log('视频生成完成:', status.url);
// 下载视频
const videoBlob = await client.downloadVideo(result.task_id);
console.log('视频大小:', videoBlob.size);
} catch (error) {
if (error instanceof VideoAPIError) {
console.error(`API错误 (${error.status}):`, error.message);
} else {
console.error('未知错误:', error);
}
}
}性能优化建议
1. 并发控制
class VideoGenerationManager {
constructor(client, maxConcurrent = 3) {
this.client = client;
this.maxConcurrent = maxConcurrent;
this.running = 0;
this.queue = [];
}
async generateVideo(params) {
return new Promise((resolve, reject) => {
this.queue.push({ params, resolve, reject });
this.processQueue();
});
}
async processQueue() {
if (this.running >= this.maxConcurrent || this.queue.length === 0) {
return;
}
this.running++;
const { params, resolve, reject } = this.queue.shift();
try {
const result = await this.client.generateVideo(params);
const status = await this.client.pollStatus(result.task_id);
resolve(status);
} catch (error) {
reject(error);
} finally {
this.running--;
this.processQueue();
}
}
}2. 缓存策略
class VideoCache {
constructor(ttl = 3600000) {
// 1小时
this.cache = new Map();
this.ttl = ttl;
}
generateKey(params) {
return JSON.stringify(params);
}
get(params) {
const key = this.generateKey(params);
const cached = this.cache.get(key);
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.result;
}
this.cache.delete(key);
return null;
}
set(params, result) {
const key = this.generateKey(params);
this.cache.set(key, {
result,
timestamp: Date.now(),
});
}
clear() {
this.cache.clear();
}
}监控和日志
1. 性能监控
class VideoAPIMonitor {
constructor() {
this.metrics = {
totalRequests: 0,
successfulRequests: 0,
failedRequests: 0,
averageResponseTime: 0,
errorTypes: new Map(),
};
}
async measureTime(fn) {
const start = Date.now();
try {
const result = await fn();
this.recordSuccess(Date.now() - start);
return result;
} catch (error) {
this.recordFailure(Date.now() - start, error);
throw error;
}
}
recordSuccess(responseTime) {
this.metrics.totalRequests++;
this.metrics.successfulRequests++;
this.updateAverageResponseTime(responseTime);
}
recordFailure(responseTime, error) {
this.metrics.totalRequests++;
this.metrics.failedRequests++;
this.updateAverageResponseTime(responseTime);
const errorType = error.constructor.name;
this.metrics.errorTypes.set(
errorType,
(this.metrics.errorTypes.get(errorType) || 0) + 1
);
}
updateAverageResponseTime(responseTime) {
const total = this.metrics.totalRequests;
this.metrics.averageResponseTime =
(this.metrics.averageResponseTime * (total - 1) + responseTime) / total;
}
getMetrics() {
return {
...this.metrics,
successRate:
this.metrics.totalRequests > 0
? this.metrics.successfulRequests / this.metrics.totalRequests
: 0,
};
}
}最佳实践总结
1. API选择
- 88API格式 (
/v1/video/generations): 适合需要更多自定义参数的场景 - OpenAI格式 (
/v1/videos): 适合与OpenAI生态系统集成的场景
2. 错误处理
- 实现指数退避重试机制
- 区分临时错误和永久错误
- 提供有意义的错误信息
3. 性能优化
- 控制并发请求数量
- 实现适当的缓存策略
- 监控API调用性能
4. 用户体验
- 提供进度反馈
- 实现超时处理
- 支持取消操作
5. 资源管理
- 及时下载生成的视频
- 清理临时文件
- 监控存储使用情况
这些最佳实践可以帮助您构建稳定、高效的视频生成应用。