forked from 77media/video-flow
7.9 KiB
7.9 KiB
视频导出流式接口 API 规范
接口概述
接口地址: POST /api/export/stream
接口类型: Server-Sent Events (SSE) 流式接口
功能描述: 实时流式视频导出,支持进度推送和高质量流复制模式
请求参数
请求头
Content-Type: application/json
Accept: text/event-stream
请求体结构
interface ExportRequest {
project_id?: string; // 项目ID(可选)
ir: IRData; // 时间轴中间表示数据(必需)
options?: ExportOptions; // 导出选项(可选)
videoFiles?: Record<string, string>; // 视频文件base64数据(可选)
}
详细参数说明
1. project_id (可选)
- 类型:
string - 描述: 项目唯一标识符
- 默认值: 如果未提供,系统会生成
default_project_{task_id前8位} - 示例:
"project_12345"
2. ir (必需) - 时间轴中间表示数据
interface IRData {
width: number; // 视频宽度(必需)
height: number; // 视频高度(必需)
fps: number; // 帧率(必需)
duration: number; // 总时长,单位毫秒(必需)
video: VideoElement[]; // 视频轨道数据(必需)
texts?: TextElement[]; // 字幕轨道数据(可选)
audio?: AudioElement[]; // 音频轨道数据(可选)
transitions?: TransitionElement[]; // 转场效果(可选)
}
VideoElement 结构
interface VideoElement {
id: string; // 视频元素唯一ID
src: string; // 视频源路径/URL/blob URL
start: number; // 在时间轴上的开始时间(毫秒)
end?: number; // 在时间轴上的结束时间(毫秒)
in: number; // 视频内部开始时间(毫秒)
out: number; // 视频内部结束时间(毫秒)
_source_type?: 'local' | 'remote_url' | 'blob'; // 源类型标识
}
TextElement 结构
interface TextElement {
id: string; // 字幕元素唯一ID
text: string; // 字幕内容
start: number; // 开始时间(毫秒)
end: number; // 结束时间(毫秒)
style?: TextStyle; // 字幕样式
}
interface TextStyle {
fontFamily?: string; // 字体,默认 'Arial'
fontSize?: number; // 字体大小,默认 40
color?: string; // 字体颜色,默认 '#FFFFFF'
backgroundColor?: string; // 背景色,默认 'transparent'
fontWeight?: 'normal' | 'bold'; // 字体粗细
fontStyle?: 'normal' | 'italic'; // 字体样式
align?: 'left' | 'center' | 'right'; // 对齐方式
shadow?: boolean; // 是否显示阴影
rotation?: number; // 旋转角度
}
3. options (可选) - 导出选项
interface ExportOptions {
quality?: 'preview' | 'standard' | 'professional'; // 质量等级
codec?: string; // 编码器,默认 'libx264'
subtitleMode?: 'hard' | 'soft'; // 字幕模式,默认 'hard'
bitrate?: string; // 比特率,如 '5000k'
preset?: string; // 编码预设,如 'medium'
}
默认值:
{
"quality": "standard",
"codec": "libx264",
"subtitleMode": "hard"
}
4. videoFiles (可选) - Base64视频数据
interface VideoFiles {
[blobId: string]: string; // blobId -> base64编码的视频数据
}
使用场景: 当 VideoElement.src 为 blob URL 时,需要提供对应的 base64 数据
完整请求示例
基础示例
{
"project_id": "demo_project_001",
"ir": {
"width": 1920,
"height": 1080,
"fps": 30,
"duration": 15000,
"video": [
{
"id": "video_1",
"src": "https://example.com/video1.mp4",
"start": 0,
"end": 10000,
"in": 2000,
"out": 12000,
"_source_type": "remote_url"
},
{
"id": "video_2",
"src": "blob:http://localhost:3000/abc-123",
"start": 10000,
"end": 15000,
"in": 0,
"out": 5000,
"_source_type": "blob"
}
],
"texts": [
{
"id": "subtitle_1",
"text": "欢迎观看演示视频",
"start": 1000,
"end": 4000,
"style": {
"fontSize": 48,
"color": "#FFFFFF",
"fontFamily": "Arial",
"align": "center"
}
}
]
},
"options": {
"quality": "professional",
"codec": "libx264",
"subtitleMode": "hard"
},
"videoFiles": {
"abc-123": "data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28y..."
}
}
响应格式 (SSE)
接口返回 Server-Sent Events 流,每个事件包含以下格式:
data: {"type": "progress", "message": "处理中...", "progress": 0.5}
事件类型
1. start - 开始事件
{
"type": "start",
"message": "开始导出...",
"timestamp": "2024-01-01T12:00:00.000Z"
}
2. progress - 进度事件
{
"type": "progress",
"stage": "preparing|stream_copy|uploading",
"message": "当前阶段描述",
"progress": 0.65,
"timestamp": "2024-01-01T12:00:30.000Z"
}
3. complete - 完成事件
{
"type": "complete",
"message": "🎬 高清视频导出完成",
"timestamp": "2024-01-01T12:01:00.000Z",
"file_size": 52428800,
"export_id": "export_abc123",
"quality_mode": "stream_copy",
"download_url": "https://cdn.example.com/video.mp4",
"cloud_storage": true
}
4. error - 错误事件
{
"type": "error",
"message": "导出失败: 文件不存在",
"timestamp": "2024-01-01T12:00:45.000Z"
}
前端集成示例
JavaScript/TypeScript
async function exportVideo(exportRequest: ExportRequest) {
const response = await fetch('/api/export/stream', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'text/event-stream'
},
body: JSON.stringify(exportRequest)
});
const reader = response.body?.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader!.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = JSON.parse(line.slice(6));
handleProgressEvent(data);
}
}
}
}
function handleProgressEvent(event: any) {
switch (event.type) {
case 'start':
console.log('导出开始');
break;
case 'progress':
console.log(`进度: ${event.progress * 100}% - ${event.message}`);
break;
case 'complete':
console.log('导出完成:', event.download_url);
break;
case 'error':
console.error('导出失败:', event.message);
break;
}
}
重要注意事项
1. 视频源处理优先级
- 本地文件路径 - 直接使用
- HTTP/HTTPS URL - 自动下载
- Blob URL - 需要提供
videoFiles中的 base64 数据
2. 高质量流复制模式
- 系统默认启用流复制模式,保持原始视频质量
- 处理速度提升 10-20 倍
- 零质量损失
3. 音频兼容性
- 自动检测混合音频情况
- 智能处理有音频/无音频片段的兼容性
4. 错误处理
- 无效视频源会被自动跳过
- 详细的错误信息通过 SSE 实时推送
5. 云存储集成
- 支持七牛云自动上传
- 上传失败时提供本地下载链接
验证接口
在正式导出前,建议先调用验证接口:
POST /api/export/validate
Content-Type: application/json
{
"ir": { /* 同导出接口的ir参数 */ },
"options": { /* 同导出接口的options参数 */ }
}
验证接口会检查:
- IR 数据完整性
- 视频分辨率、帧率、时长
- 导出选项有效性
- 返回详细的验证错误信息