cdn-url-transfer

Pass

将模型配置中的外部示例 URL(fal.media、googleapis 等)转存到速推 CDN(cdn-video.51sux.com),并更新代码和校验 API 返回。当用户提到"转存 CDN"、"替换示例链接"、"转存链接"、"CDN 地址"、"示例 URL 替换"时使用此 skill。

@openclaw
MIT2/22/2026
(0)
1.0k
3
3

Install Skill

Skills are third-party code from public GitHub repositories. SkillHub scans for known malicious patterns but cannot guarantee safety. Review the source code before installing.

Install globally (user-level):

npx skillhub install openclaw/skills/cdn-url-transfer

Install in current project:

npx skillhub install openclaw/skills/cdn-url-transfer --project

Suggested path: ~/.claude/skills/cdn-url-transfer/

SKILL.md Content

---
name: cdn-url-transfer
description: 将模型配置中的外部示例 URL(fal.media、googleapis 等)转存到速推 CDN(cdn-video.51sux.com),并更新代码和校验 API 返回。当用户提到"转存 CDN"、"替换示例链接"、"转存链接"、"CDN 地址"、"示例 URL 替换"时使用此 skill。
---

# 模型示例 URL 转存 CDN

将模型配置中的外部文件链接(fal.media、googleapis 等)转存到速推 CDN,确保示例资源稳定可访问。

## 需替换的 URL 位置

每个模型最多有 **3 处** URL 需要替换,全部在 `model_registry.py` 中:

| 位置 | 字段 | 说明 |
|------|------|------|
| 1 | `parameters[].examples` | 输入参数的示例值(图片/视频 URL) |
| 2 | `output_example` | 输出结果示例中的媒体 URL |
| 3 | executor 的 `get_params_schema()` | 执行器中的参数 schema(与位置 1 保持同步) |

**关键文件:**
- **主数据源**(docs API 读取):`translate_api/app/api/v3/transports/mcp/model_registry.py`
- **执行器**(运行时使用):`translate_api/app/api/v3/executors/` 下对应的 executor 文件

## 操作流程

### Step 1: 扫描目标模型的外部 URL

用 Grep 在 `model_registry.py` 中搜索目标模型相关的外部域名:

```
搜索模式: fal\.media|googleapis\.com|其他外部域名
范围: model_registry.py 中目标模型的注册块
```

同时搜索对应 executor 文件中的 `examples` 字段。

### Step 2: 上传文件到 CDN

#### 方案 A:MCP `upload_image` 工具(仅限小图片 base64)

> **已知问题**:`upload_image` 的 `image_url` 参数(URL 转存模式)**经常失败**,返回空错误。
> 仅 `image_data`(base64 模式)可靠,但受工具参数大小限制,仅适合 **< 100KB** 的小图片。

```
upload_image(
  image_data="<base64字符串>",
  file_name="模型名_用途.png",
  folder="模型名-examples"
)
```

#### 方案 B:curl 下载 + TOS Python SDK 直传(推荐)

这是最可靠的方案,支持**任意文件类型和大小**(图片、音频、视频)。

**第一步:用 curl 下载到本地**(curl 不走 Python 代理,更稳定)

```bash
curl -sL -o /tmp/文件名.png "原始外部URL"
curl -sL -o /tmp/文件名.mp3 "原始外部URL"
```

**第二步:用 TOS SDK 上传到 CDN**

```python
import tos

TOS_CONFIG = {
    'access_key': 'AKLTZTBhMDdlYTdlODdlNGFlNGFjNTliOGEwOWFkNzk0Mjk',
    'secret_key': 'TnpVMk9EUmtNREkzWmpjNU5EazVNVGxsTkRnMk9XUXlZMk15WldRNVpqUQ==',
    'endpoint': 'tos-cn-guangzhou.volces.com',
    'region': 'cn-guangzhou',
    'bucket_name': 'fal-task',
    'public_domain': 'https://cdn-video.51sux.com'
}

client = tos.TosClientV2(
    TOS_CONFIG['access_key'],
    TOS_CONFIG['secret_key'],
    TOS_CONFIG['endpoint'],
    TOS_CONFIG['region']
)

# 读取本地文件并上传
with open('/tmp/文件名.png', 'rb') as f:
    data = f.read()

object_key = '{模型名}-examples/{文件名}.png'
client.put_object(
    bucket=TOS_CONFIG['bucket_name'],
    key=object_key,
    content=data,
    content_type='image/png'  # 按实际类型设置
)

cdn_url = f"{TOS_CONFIG['public_domain']}/{object_key}"
print(cdn_url)
```

#### 方案 C:catbox 中转(备选)

当 Google Cloud Storage 等外部链接从本机无法直接访问时,可先用 catbox 做跳板:

```bash
# 1. 先用 curl 下载(如果 curl 能访问的话)
curl -sL -o /tmp/文件.png "原始外部URL"
# 2. 上传到 catbox 获取临时链接
curl -sF "reqtype=fileupload" -F "fileToUpload=@/tmp/文件.png" https://catbox.moe/user/api.php
# 3. 再从 catbox 链接走方案 B 上传到 TOS
```

> catbox 链接仅做中转用,最终必须传到 TOS CDN。catbox 文件可能过期。

**CDN 存储路径命名规范:**

| 元素 | 规范 | 示例 |
|------|------|------|
| 文件夹 | `{模型简称}-examples/` | `omnihuman-examples/`、`dreamactor-examples/` |
| 文件名 | `{模型简称}_{用途}.{扩展名}` | `omnihuman_v15_input_image.png` |

**常见 content_type 对照:**

| 文件类型 | content_type |
|----------|-------------|
| PNG 图片 | `image/png` |
| JPEG 图片 | `image/jpeg` |
| MP4 视频 | `video/mp4` |
| MP3 音频 | `audio/mpeg` |
| WAV 音频 | `audio/wav` |

### Step 3: 替换代码中的 URL

按顺序替换以下位置:

1. **model_registry.py** 中 `parameters[].examples` 里的 URL
2. **model_registry.py** 中 `output_example` 里的 URL
3. **executor 文件** 中 `get_params_schema()` 里的 `examples` URL

使用 StrReplace 工具精确替换,每次替换一个 URL。

### Step 4: 重启服务并校验

> **注意**:`kill -HUP` 对 multiprocessing worker 进程无效。需要完整重启服务。

```bash
# 1. 找到 8002 端口进程
lsof -i :8002 -P | head -5

# 2. 杀掉旧进程
kill <PID>

# 3. 以 reload 模式重启(方便后续修改自动生效)
cd translate_api && python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8002 --reload

# 4. 等待启动完成
sleep 3

# 5. 请求 docs API 校验
curl -s "http://127.0.0.1:8002/api/v3/models/<URL编码的模型ID>/docs" \
  -H "Content-Type: application/json" | python3 -c "
import sys, json, re
data = json.load(sys.stdin)['data']
raw = json.dumps(data)

# 检查外部域名残留
external = re.findall(r'https?://(?:v3b?\.fal\.media|storage\.googleapis\.com)[^\"\s]*', raw)
if external:
    print('❌ 仍有外部链接残留:')
    for u in external:
        print(f'  {u}')
else:
    print('✅ 所有外部链接已替换为 CDN 地址')

# 展示当前所有 CDN 链接
cdns = re.findall(r'https?://cdn-video\.51sux\.com[^\"\s]*', raw)
if cdns:
    print(f'\n当前 CDN 链接(共 {len(cdns)} 个):')
    for u in set(cdns):
        print(f'  ✅ {u}')
"

# 6. 验证 CDN 文件可访问
curl -sI "CDN链接" | head -3
# 应返回 HTTP/2 200 + 正确的 content-type
```

## 校验清单

- [ ] `model_registry.py` 中参数 examples 已替换
- [ ] `model_registry.py` 中 output_example 已替换
- [ ] executor 文件中 get_params_schema 的 examples 已替换
- [ ] 服务已重启(旧进程可能是 orphaned multiprocessing worker,PPID=1)
- [ ] docs API 返回无外部域名残留
- [ ] 每个 CDN 链接均返回 HTTP 200 + 正确 content-type

## 注意事项

### 1. MCP `upload_image` 工具的局限性

- **URL 转存模式(`image_url` 参数)不可靠**,经实测对 googleapis、catbox 等多种域名均返回空错误
- **base64 模式可用但有大小限制**,仅适合 < 100KB 的小文件
- **不支持非图片文件**(音频、视频),即使指定 content_type 也不行
- **推荐使用方案 B**(curl + TOS SDK),支持任意文件类型和大小

### 2. 网络/代理问题

- **Python `requests` 库**走系统代理,访问 catbox.moe 等外部站点会报 `ProxyError`
- **`curl` 命令**通常不受此影响,可正常下载外部文件
- 因此下载外部文件务必用 `curl`,不要用 Python `requests`

### 3. 服务重启

- API 进程可能是 **orphaned multiprocessing worker**(PPID=1),`kill -HUP` 无效
- 必须 `kill` 进程后手动重启
- 建议用 `--reload` 模式启动,后续代码修改自动生效
- 重启后需等待 2-3 秒再校验,确保模块加载完成

### 4. 存储信息

| 配置项 | 值 |
|--------|-----|
| 存储服务 | 火山 TOS(cn-guangzhou) |
| Bucket | `fal-task` |
| CDN 域名 | `https://cdn-video.51sux.com` |
| SDK | `import tos`(需 `pip install tos`) |
| 最终 URL 格式 | `https://cdn-video.51sux.com/{object_key}` |

### 5. 常见外部域名(需替换的源)

| 域名 | 来源 |
|------|------|
| `storage.googleapis.com/falserverless/` | fal.ai 官方示例 |
| `v3.fal.media/` | fal.ai 生成结果 |
| `v3b.fal.media/` | fal.ai 生成结果(备用) |
| `files.catbox.moe/` | catbox 临时图床(仅中转用) |