128 lines
4.1 KiB
Markdown
128 lines
4.1 KiB
Markdown
# DashScope 本地视频文件路径格式问题 - 根因分析
|
||
|
||
## 问题描述
|
||
|
||
调用 DashScope API 时返回错误:
|
||
```
|
||
<400> InternalError.Algo.InvalidParameter: The provided URL does not appear to be valid. Ensure it is correctly formatted.
|
||
```
|
||
|
||
## 当前实现分析
|
||
|
||
### 尝试的方法 1:直接使用绝对路径
|
||
```python
|
||
video_path_for_api = str(video_path.absolute())
|
||
# 例如:/Users/d-robotics/workSpace/videoSummary/uploads/episode_0_model_input_observation_full_image.mp4
|
||
```
|
||
**结果**:失败,返回 400 错误
|
||
|
||
### 尝试的方法 2:使用 file:// 格式
|
||
```python
|
||
file_url = f"file://{absolute_path_str}"
|
||
# 例如:file:///Users/d-robotics/workSpace/videoSummary/uploads/episode_0_model_input_observation_full_image.mp4
|
||
```
|
||
**结果**:失败,返回 400 错误
|
||
|
||
## 根因分析
|
||
|
||
### 1. 路径格式问题
|
||
|
||
根据 DashScope 官方文档示例:
|
||
```python
|
||
local_path = "xxx/test.mp4" # 绝对路径字符串
|
||
video_path = f"file://{local_path}"
|
||
```
|
||
|
||
**关键发现**:
|
||
- 文档示例中 `local_path` 是**绝对路径字符串**,不包含前导斜杠
|
||
- 但在 macOS/Linux 系统上,绝对路径通常以 `/` 开头
|
||
- 当使用 `file://` 前缀时,如果路径以 `/` 开头,应该使用 `file:///`(三个斜杠)而不是 `file://`(两个斜杠)
|
||
|
||
### 2. URL 编码问题
|
||
|
||
路径中可能包含特殊字符(虽然当前路径没有),但 `file://` URL 格式要求路径部分需要进行 URL 编码:
|
||
- 空格应该编码为 `%20`
|
||
- 其他特殊字符也需要编码
|
||
|
||
### 3. 可能的解决方案
|
||
|
||
#### 方案 A:使用正确的 file:// 格式(推荐)
|
||
|
||
根据 RFC 3986 和 file:// URL 规范:
|
||
- 在 Unix/macOS 系统上,`file://` URL 应该使用三个斜杠:`file:///`
|
||
- 路径应该进行 URL 编码
|
||
|
||
```python
|
||
from urllib.parse import quote, urljoin
|
||
import os
|
||
|
||
absolute_path = video_path.absolute()
|
||
absolute_path_str = str(absolute_path)
|
||
|
||
# 对于 Unix/macOS 系统,使用 file:/// 格式
|
||
if os.name != 'nt': # Unix/macOS
|
||
# 移除前导斜杠,然后添加 file:///
|
||
path_without_leading_slash = absolute_path_str.lstrip('/')
|
||
file_url = f"file:///{path_without_leading_slash}"
|
||
# 或者直接使用 file:/// 加上完整路径
|
||
file_url = f"file://{absolute_path_str}"
|
||
else: # Windows
|
||
# Windows 路径需要特殊处理
|
||
file_url = f"file:///{absolute_path_str.replace('\\', '/')}"
|
||
```
|
||
|
||
#### 方案 B:直接使用绝对路径字符串(如果 SDK 支持)
|
||
|
||
根据文档示例,可能 SDK 内部会自动处理 `file://` 前缀,所以应该直接传递绝对路径字符串:
|
||
|
||
```python
|
||
video_path_for_api = str(video_path.absolute())
|
||
```
|
||
|
||
#### 方案 C:使用 pathlib 的 as_uri() 方法
|
||
|
||
Python 的 `pathlib.Path` 提供了 `as_uri()` 方法,可以生成正确的 file:// URL:
|
||
|
||
```python
|
||
video_path_for_api = video_path.absolute().as_uri()
|
||
# 这会自动生成正确的 file:// URL 格式
|
||
```
|
||
|
||
## 推荐解决方案
|
||
|
||
**使用 `pathlib.Path.as_uri()` 方法**,这是最可靠的方式,因为:
|
||
1. Python 标准库方法,符合 RFC 3986 规范
|
||
2. 自动处理不同操作系统的路径格式
|
||
3. 自动处理特殊字符编码
|
||
4. 生成正确的 file:// URL 格式
|
||
|
||
### 实现代码
|
||
|
||
```python
|
||
def analyze_video(self, video_path: Path, prompt: str, fps: Optional[int] = None) -> Dict[str, Any]:
|
||
# ... existing code ...
|
||
|
||
# Use pathlib's as_uri() method to generate correct file:// URL
|
||
absolute_path = video_path.absolute()
|
||
video_path_for_api = absolute_path.as_uri()
|
||
|
||
# Log for debugging
|
||
logger.info(f"Using video path (file:// URI): {video_path_for_api}")
|
||
|
||
# ... rest of the code ...
|
||
```
|
||
|
||
## 验证步骤
|
||
|
||
1. 使用 `pathlib.Path.as_uri()` 生成 file:// URL
|
||
2. 验证生成的 URL 格式是否正确
|
||
3. 测试调用 DashScope API
|
||
4. 如果仍然失败,检查 DashScope SDK 文档是否有其他要求
|
||
|
||
## 注意事项
|
||
|
||
- DashScope API 可能需要在服务器端能够访问该文件路径
|
||
- 如果 API 服务器运行在不同的机器上,本地文件路径将无法访问
|
||
- 在这种情况下,可能需要将文件上传到可访问的 URL(如 OSS),或使用其他方式传递文件内容
|
||
|