# Marlin-2B Video VLM API 文档 ## 基础信息 - 服务地址:`http://0.0.0.0:8900` - 模型:Marlin-2B - 设备:Apple Silicon (MPS) / CUDA / CPU --- ## 1. 健康检查接口 **接口路径**:`GET /health` **请求示例**: ```bash curl http://localhost:8900/health ``` **返回参数**: | 字段名 | 类型 | 说明 | |--------|------|------| | status | string | 状态:ok(已加载)或 loading(加载中) | | model | string | 模型名称,固定为 "Marlin-2B" | | device | string | 运行设备:mps/cuda/cpu | **返回示例**: ```json { "status": "ok", "model": "Marlin-2B", "device": "mps" } ``` --- ## 2. 视频字幕生成接口 **接口路径**:`POST /caption` **功能说明**:为视频生成结构化字幕,包括场景描述和带时间戳的事件列表。 **请求参数**(multipart/form-data): | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | video | 文件 | 是 | 视频文件(支持 mp4, avi, mov, webm 等格式) | | max_new_tokens | int | 否 | 最大生成 token 数,默认值 2048 | **请求示例**: ```bash curl -X POST http://localhost:8900/caption \ -F "video=@/path/to/video.mp4" \ -F "max_new_tokens=2048" ``` **返回参数**: | 字段名 | 类型 | 说明 | |--------|------|------| | caption | string \| null | 完整的原始字幕文本 | | scene | string \| null | 场景描述段落 | | events | array \| null | 事件列表,每个事件包含 start/end/description | **events 数组元素**: | 字段名 | 类型 | 说明 | |--------|------|------| | start | float | 事件开始时间(秒) | | end | float | 事件结束时间(秒) | | description | string | 事件描述 | **返回示例**: ```json { "caption": "Scene: ... Events: ...", "scene": "这是一个室内场景...", "events": [ { "start": 0.0, "end": 5.0, "description": "一个人走进房间" }, { "start": 5.5, "end": 10.0, "description": "这个人坐在沙发上" } ] } ``` --- ## 3. 事件时间定位接口 **接口路径**:`POST /find` **功能说明**:在视频中查找指定事件发生的时间区间(时间定位)。 **请求参数**(multipart/form-data): | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | video | 文件 | 是 | 视频文件 | | event | 字符串 | 是 | 自然语言事件查询,例如 "一个人进入房间" | **请求示例**: ```bash curl -X POST http://localhost:8900/find \ -F "video=@/path/to/video.mp4" \ -F "event=一个人进入房间" ``` **返回参数**: | 字段名 | 类型 | 说明 | |--------|------|------| | raw | string \| null | 原始模型输出,例如 "From 14.3 to 18.2." | | span | array \| null | 时间区间 [开始时间, 结束时间],单位秒 | | format_ok | bool | 输出格式是否符合训练格式 | **返回示例**: ```json { "raw": "From 14.3 to 18.2.", "span": [14.3, 18.2], "format_ok": true } ``` --- ## 4. 自定义提示生成接口 **接口路径**:`POST /generate` **功能说明**:使用自定义提示词与视频进行交互,实现更灵活的问答。 **注意**:此接口需要安装 `torchvision` 库才能正常工作。 **请求参数**(multipart/form-data): | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | video | 文件 | 是 | 视频文件 | | prompt | 字符串 | 是 | 自定义文本提示词 | | max_new_tokens | int | 否 | 最大生成 token 数,默认值 512 | | do_sample | bool | 否 | 是否启用采样,默认 false(确定性输出) | | temperature | float | 否 | 温度参数,控制随机性,默认 1.0 | | top_p | float | 否 | top-p 采样参数,默认 1.0 | **请求示例**: ```bash curl -X POST http://localhost:8900/generate \ -F "video=@/path/to/video.mp4" \ -F "prompt=描述这个视频的内容" \ -F "max_new_tokens=512" \ -F "temperature=0.7" ``` **返回参数**: | 字段名 | 类型 | 说明 | |--------|------|------| | text | string | 生成的文本内容 | **返回示例**: ```json { "text": "这个视频展示了..." } ``` --- ## 5. 字幕叠加任务接口 **服务地址**:`http://127.0.0.1:3010` ### 5.1 创建字幕叠加任务 **接口路径**:`POST /video/caption` **功能说明**:将背景视频、字幕、文字/图片元素、背景音频合成输出最终视频。异步执行,返回 taskId。 **请求参数**(Content-Type: `application/json`): | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | video_urls | string[] | **是** | 背景视频 URL 列表,多个会自动拼接 | | audio_url | string | 否 | 背景音频 URL(配音/BGM),原视频会被消音 | | subtitles | SubtitleSegment[] | 否 | 字幕时间线列表 | | subtitle_style | SubtitleStyle | 否 | 字幕样式配置 | | elements | CaptionElement[] | 否 | 文字/图片元素列表 | | callback_url | string | 否 | 任务完成回调地址 | **SubtitleSegment(字幕时间线片段):** | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | start | float | **是** | 开始时间(秒) | | end | float | **是** | 结束时间(秒) | | text | string | **是** | 字幕文本 | **SubtitleStyle(字幕样式):** | 字段 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | fontSize | int | 否 | 28 | 字号(px) | | fontColor | string | 否 | `#FFFFFF` | 字体颜色(十六进制) | | bgColor | string | 否 | `#000000` | 字幕背景色,空=透明 | | bgOpacity | float | 否 | 0.6 | 背景透明度,0-1 | | x | string | 否 | `"center"` | 水平位置:`"left"`/`"center"`/`"right"` 或像素值如 `"100"` | | y | string | 否 | `"bottom"` | 垂直位置:`"top"`/`"center"`/`"bottom"`、像素值如 `"200"`、或 CSS 表达式如 `"calc(100% - 300px)"` | **CaptionElement(自定义元素):** | 字段 | 类型 | 必填 | 默认值 | 说明 | |------|------|------|--------|------| | type | string | **是** | - | 元素类型:`"text"` 或 `"image"` | | text | string | type=text时必填 | - | 文字内容 | | imageUrl | string | type=image时必填 | - | 图片下载 URL | | x | string | 否 | `"center"` | 水平位置:`"left"`/`"center"`/`"right"` 或像素值 | | y | string | 否 | `"center"` | 垂直位置:`"top"`/`"center"`/`"bottom"`、像素值、或 `calc()` | | fontSize | int | 否 | 36 | 字号(px,type=text有效) | | fontColor | string | 否 | `#FFFFFF` | 字体颜色 | | bgColor | string | 否 | 透明 | 背景色,如 `"#FFFF00"` | | bgOpacity | float | 否 | 1.0 | 背景透明度,0-1 | | width | int | 否 | 原图尺寸 | 图片显示宽度(px,type=image有效) | | height | int | 否 | 原图尺寸 | 图片显示高度(px,type=image有效) | | startTime | float | 否 | 0 | 开始显示时间(秒),0=立即显示 | | duration | float | 否 | 0 | 持续时长(秒),0=一直显示到结束 | | trackIndex | int | 否 | 1 | 层级(类似 z-index),越大越靠前 | | animation | string | 否 | 无 | 动画:`"fadeIn"`/`"slideUp"`/`"slideLeft"`/`"scaleIn"` | **请求示例:** ```bash curl --location --request POST 'http://127.0.0.1:3010/video/caption' \ --header 'Content-Type: application/json' \ --data-raw '{ "video_urls": [ "http://example.com/video1.mp4", "http://example.com/video2.mp4" ], "audio_url": "http://example.com/audio.mp3", "subtitles": [ {"start": 0.0, "end": 3.0, "text": "第一段字幕"}, {"start": 3.0, "end": 6.0, "text": "第二段字幕"} ], "subtitle_style": { "fontSize": 36, "fontColor": "#FFFF00", "bgColor": "#000000", "bgOpacity": 0.7, "x": "center", "y": "bottom" }, "elements": [ { "type": "text", "text": "标题文字", "x": "center", "y": "60", "fontSize": 48, "fontColor": "#FF0000", "startTime": 0, "duration": 0, "trackIndex": 5, "animation": "fadeIn" }, { "type": "image", "imageUrl": "http://example.com/logo.png", "x": "right", "y": "top", "width": 100, "height": 100, "startTime": 0, "duration": 0, "trackIndex": 5 } ], "callback_url": "https://your-server.com/callback" }' ``` **返回参数:** | 字段名 | 类型 | 说明 | |--------|------|------| | taskId | string | 任务 ID,用于后续查询结果 | **返回示例:** ```json { "taskId": "CAPTION_20260602123456_abc123" } ``` --- ### 5.2 查询字幕任务结果 **接口路径**:`GET /video/caption/{taskId}` **功能说明**:根据 taskId 查询字幕叠加任务的状态和输出文件。 **路径参数:** | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | taskId | string | **是** | 创建任务时返回的 taskId | **返回参数:** | 字段名 | 类型 | 说明 | |--------|------|------| | taskId | string | 任务 ID | | status | string | 任务状态:`"running"`(处理中)/ `"completed"`(完成)/ `"failed"`(失败) | | fileUrl | string | 完成时返回:输出视频下载 URL | | fileSize | int64 | 完成时返回:输出文件大小(字节) | | fileName | string | 完成时返回:输出文件名 | | durationStr | string | 完成时返回:视频时长(如 "0:45") | | errorMessage | string | 失败时返回:错误信息 | **返回示例(完成时):** ```json { "taskId": "CAPTION_20260602123456_abc123", "status": "completed", "fileUrl": "http://127.0.0.1:3010/storage/output.mp4", "fileSize": 5242880, "fileName": "output.mp4", "durationStr": "0:45" } ``` **返回示例(处理中):** ```json { "taskId": "CAPTION_20260602123456_abc123", "status": "running" } ``` **返回示例(失败):** ```json { "taskId": "CAPTION_20260602123456_abc123", "status": "failed", "errorMessage": "视频下载失败" } ``` 当请求失败时,接口返回 HTTP 错误码和错误信息: | HTTP 状态码 | 说明 | |-------------|------| | 400 | 请求参数错误 | | 500 | 服务器内部错误 | | 503 | 模型尚未加载完成 | **错误响应示例**: ```json { "detail": "Caption failed: 错误详情" } ```