# Chanjing Avatar

> Use Chanjing Avatar API for lip-syncing video generation (upload audio/video, create tasks, poll results).

- Skill: `chanjing-ai/chanjing-avatar` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add chanjing-ai/chanjing-avatar`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chanjing-ai/chanjing-avatar/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Integrations & APIs
- Author: chanjing-ai (https://skillmd.com/u/chanjing-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chanjing-ai/chanjing-avatar

---


# Chanjing Avatar (Lip-Syncing)

## 功能说明

调用蝉镜 **Avatar** Open API：上传音视频素材、创建对口型任务、轮询与获取结果链接。脚本为 Python HTTP/上传客户端，**不**依赖 ffmpeg/ffprobe。

## 运行依赖

- **python3** 与同仓库 `scripts/*.py`
- **无** ffmpeg/ffprobe 门控

## 环境变量与机器可读声明

- 环境变量键名与说明：**`manifest.yaml`**（`environment` 段）及本文
- 变量、凭据、合规 **`permissions`**、**`clientPermissions`、`agentPolicy`**：**`manifest.yaml`**

## 使用命令

- **ClawHub**（slug 以注册表为准）：`clawhub run chanjing-avatar`
- **本仓库**：`python skills/chanjing-avatar/scripts/create_task.py …`（流程见正文 **How to Use**）

---

## 登记与审稿（单一事实来源）

主凭据、上传/下载边界、浏览器引导等：**以 `manifest.yaml` 为准**。本篇 **How to Use** 起为 API 步骤说明。

## When to Use This Skill

Use this skill when the user needs to create lip-syncing videos (digital avatar videos) with synchronized mouth movements.

Chanjing Avatar supports:

* Text-driven or audio-driven lip-syncing
* Multiple system voices for TTS
* Video resolution customization
* Task status polling and callback

## How to Use This Skill

**前置条件**：执行本 Skill 前，必须先通过 **chanjing-credentials-guard** 完成 AK/SK 与 Token 校验。凭据与审稿对表见 **`manifest.yaml`**。

### Security & credentials（引用）

详见 **`manifest.yaml`** 中 **`credentials`** 与 **`clientPermissions`**（含本地上传、结果 URL、浏览器行为；合规见顶层 **`permissions`**）。

Multiple APIs need to be invoked. All share the domain: "https://open-api.chanjing.cc".
All requests communicate using json.
You should use utf-8 to encode and decode text throughout this task.

1. Obtain an `access_token`, which is required for all subsequent API calls
2. Upload your video/audio files using the File Management API to get `file_id`
3. Create a lip-syncing task with video and audio/text using these `file_id` values
4. Poll the Query Task Detail API or use Task List API to check status
5. Download the generated video using the url in response when status is completed

### Obtain AccessToken

从 `~/.chanjing/credentials.json` 读取 `app_id` 和 `secret_key`，若无有效 Token 则调用：

```http
POST /open/v1/access_token
Content-Type: application/json
```

请求体（使用本地配置的 app_id、secret_key）：

```json
{
  "app_id": "<从 credentials.json 读取>",
  "secret_key": "<从 credentials.json 读取>"
}
```

Response example:

```json
{
  "trace_id": "8ff3fcd57b33566048ef28568c6cee96",
  "code": 0,
  "msg": "success",
  "data": {
    "access_token": "1208CuZcV1Vlzj8MxqbO0kd1Wcl4yxwoHl6pYIzvAGoP3DpwmCCa73zmgR5NCrNu",
    "expire_in": 1721289220
  }
}
```

Response field description:

| First-level Field | Second-level Field | Description |
|---|---|---|
| code | | Response status code |
| msg | | Response message |
| data | | Response data |
| | access_token | Valid for one day, previous token will be invalidated |
| | expire_in | Token expiration time |

Response Status Code Description

| Code | Description |
|---|---|
| 0 | Success |
| 400 | Invalid parameter format |
| 40000 | Parameter error |
| 50000 | System internal error |

### Upload Media Files (File Management)

Before creating a lip-syncing task, you **must** upload your video (and optional audio) files using the File Management API to obtain `file_id` values.

The full documentation is here: `[File Management](https://doc.chanjing.cc/api/file/file-management.html)`.

#### Step 1: Get upload URL

```http
GET /open/v1/common/create_upload_url
access_token: {{access_token}}
```

Query params:

| Key | Example | Description |
|---|---|---|
| service | lip_sync_video / lip_sync_audio | File usage purpose. Use `lip_sync_video` for driving video, `lip_sync_audio` for audio (if audio-driven). |
| name | 1.mp4 | Original file name including extension |

You will get a response containing `sign_url`, `mime_type`, and `file_id`. Use the `sign_url` with HTTP `PUT` to upload the file, setting `Content-Type` to the returned `mime_type`. After the PUT completes, **poll the file detail API** until the file is ready (do not assume a fixed wait). Keep the returned `file_id` for `video_file_id` / `audio_file_id` below.

**Polling:** Call `GET /open/v1/common/file_detail?id={{file_id}}` with `access_token` until the response `data.status` indicates success (e.g. `status === 2`). Only then use the `file_id` for the create task API.

### Create Lip-Syncing Task

Submit a lip-syncing video creation task, which returns a video ID for polling later.

```http
POST /open/v1/video_lip_sync/create
access_token: {{access_token}}
Content-Type: application/json
```

Request body example (TTS-driven):

```json
{
  "video_file_id": "e284db4d95de4220afe78132158156b5",
  "screen_width": 1080,
  "screen_height": 1920,
  "callback": "https://example.com/openapi/callback",
  "model": 0,
  "audio_type": "tts",
  "tts_config": {
    "text": "君不见黄河之水天上来，奔流到海不复回。",
    "audio_man_id": "C-f2429d07554749839849497589199916",
    "speed": 1,
    "pitch": 1
  }
}
```

Request body example (Audio-driven):

```json
{
  "video_file_id": "e284db4d95de4220afe78132158156b5",
  "screen_width": 1080,
  "screen_height": 1920,
  "model": 0,
  "audio_type": "audio",
  "audio_file_id": "audio_file_id_from_file_management"
}
```

Request field description:

| Parameter Name | Type | Required | Description |
|---|---|---|---|
| video_file_id | string | Yes | Video file ID from File Management (`data.file_id`). Supports mp4, mov, webm |
| screen_width | int | No | Screen width, default 1080 |
| screen_height | int | No | Screen height, default 1920 |
| backway | int | No | Playback order when reaching end: 1-normal, 2-reverse. Default 1 |
| drive_mode | string | No | Drive mode: ""-normal, "random"-random frame. Default "" |
| callback | string | No | Callback URL for async notification |
| model | int | No | Model version: 0-basic, 1-high quality. Default 0 |
| audio_type | string | No | Audio type: "tts"-text driven, "audio"-audio driven. Default "tts" |
| tts_config | object | Yes (for tts) | TTS configuration when audio_type="tts" |
| tts_config.text | string | Yes (for tts) | Text to synthesize |
| tts_config.audio_man_id | string | Yes (for tts) | Voice ID |
| tts_config.speed | number | No | Speech speed: 0.5-2, default 1 |
| tts_config.pitch | number | No | Pitch, default 1 |
| audio_file_id | string | Yes (for audio) | Audio file ID from File Management (`data.file_id`) when `audio_type="audio"`. Supports mp3, m4a, wav |
| volume | int | No | Volume: 1-100, default 100 |

Response example:

```json
{
  "trace_id": "8d10659438827bd4d59eaa2696f9d391",
  "code": 0,
  "msg": "success",
  "data": "9499ed79995c4bdb95f0d66ca84419fd"
}
```

Response field description:

| Field | Description |
|---|---|
| code | Response status code |
| msg | Response message |
| data | Video ID for subsequent polling |

### Query Task List

Get a list of lip-syncing tasks.

```http
POST /open/v1/video_lip_sync/list
access_token: {{access_token}}
Content-Type: application/json
```

Request body:

```json
{
  "page": 1,
  "page_size": 10
}
```

Request field description:

| Parameter | Type | Required | Description |
|---|---|---|---|
| page | int | No | Page number, default 1 |
| page_size | int | No | Page size, default 10 |

Response example:

```json
{
  "trace_id": "8d10659438827bd4d59eaa2696f9d391",
  "code": 0,
  "msg": "success",
  "data": {
    "list": [
      {
        "id": "9499ed79995c4bdb95f0d66ca84419fd",
        "status": 20,
        "progress": 100,
        "msg": "success",
        "video_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.mp4",
        "preview_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.jpg",
        "duration": 300,
        "create_time": 1738636800
      }
    ],
    "page_info": {
      "page": 1,
      "size": 10,
      "total_count": 1,
      "total_page": 1
    }
  }
}
```

Response field description:

| First-level Field | Second-level Field | Description |
|---|---|---|
| code | | Response status code |
| msg | | Response message |
| data | | Response data |
| | list | Task list |
| | | id: Video ID |
| | | status: Task status (0-pending, 10-generating, 20-success, 30-failed) |
| | | progress: Progress 0-100 |
| | | msg: Task message |
| | | video_url: Video download URL |
| | | preview_url: Cover image URL |
| | | duration: Video duration in ms |
| | | create_time: Creation time (unix timestamp) |
| | page_info | Pagination info |

### Query Task Detail

Poll the following API to check task status until completed.

```http
GET /open/v1/video_lip_sync/detail
access_token: {{access_token}}
```

Query params:

| Parameter | Description |
|---|---|
| id | Video ID |

Example: `GET /open/v1/video_lip_sync/detail?id=9499ed79995c4bdb95f0d66ca84419fd`

Response example:

```json
{
  "trace_id": "8d10659438827bd4d59eaa2696f9d391",
  "code": 0,
  "msg": "success",
  "data": {
    "id": "9499ed79995c4bdb95f0d66ca84419fd",
    "status": 20,
    "progress": 100,
    "msg": "success",
    "video_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.mp4",
    "preview_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.jpg",
    "duration": 300,
    "create_time": 1738636800
  }
}
```

Response field description:

| First-level Field | Second-level Field | Description |
|---|---|---|
| code | | Response status code |
| msg | | Response message |
| data | | Response data |
| | id | Video ID |
| | status | Task status: 0-pending, 10-generating, 20-success, 30-failed |
| | progress | Progress 0-100 |
| | msg | Task message |
| | video_url | Video download URL |
| | preview_url | Cover image URL |
| | duration | Video duration in ms |
| | create_time | Creation time (unix timestamp) |

### Callback Notification

When a callback URL is provided, the system will send a POST request when the task completes:

```json
{
  "trace_id": "8d10659438827bd4d59eaa2696f9d391",
  "code": 0,
  "msg": "success",
  "data": {
    "id": "9499ed79995c4bdb95f0d66ca84419fd",
    "status": 20,
    "progress": 100,
    "msg": "success",
    "video_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.mp4",
    "preview_url": "https://res.chanjing.cc/xxx/lip-sync/9499ed79995c4bdb95f0d66ca84419fd.jpg",
    "duration": 300,
    "create_time": 1738636800
  }
}
```

## Scripts

本 Skill 提供脚本（`skills/chanjing-avatar/scripts/`），与 **chanjing-credentials-guard** 使用同一配置文件（`~/.chanjing/credentials.json`）获取 Token。

| 脚本 | 说明 |
|------|------|
| `get_upload_url.py` | 获取上传链接，输出 `sign_url`、`mime_type`、`file_id` |
| `upload_file.py` | 上传本地文件，轮询 file_detail 直到就绪后输出 `file_id` |
| `create_task.py` | 创建对口型任务（TTS 或音频驱动），输出视频任务 id |
| `poll_task.py` | 轮询任务直到完成，输出 `video_url` |

示例（在项目根或 skill 目录下执行）：

```bash
# 1. 上传驱动视频，得到 video_file_id
VIDEO_FILE_ID=$(python skills/chanjing-avatar/scripts/upload_file.py --service lip_sync_video --file ./my_video.mp4)

# 2. 创建 TTS 对口型任务（需先通过 list_common_audio 获取 audio_man_id）
TASK_ID=$(python skills/chanjing-avatar/scripts/create_task.py \
  --video-file-id "$VIDEO_FILE_ID" \
  --text "君不见黄河之水天上来" \
  --audio-man-id "C-f2429d07554749839849497589199916")

# 3. 轮询直到完成，得到视频下载链接
python skills/chanjing-avatar/scripts/poll_task.py --id "$TASK_ID"
```

音频驱动时：先上传音频得到 `audio_file_id`，再 `create_task.py --video-file-id <id> --audio-file-id <audio_file_id>`。

## Response Status Code Description

| Code | Description |
|---|---|
| 0 | Response successful |
| 10400 | AccessToken verification failed |
| 40000 | Parameter error |
| 40001 | Exceeds RPM/QPS limit |
| 50000 | System internal error |


