Skill: binkes/chanjing-avatar (version 1.0.7)

--- name: chanjing-avatar description: >- Use Chanjing Avatar API for lip-syncing video generation (upload audio/video, create tasks, poll results). credential: credentials.json (app_id/secret_key; access_token persisted on disk) openclaw_primary_env: false environment: CHANJING_OPENAPI_CREDENTIALS_DIR, CHANJING_OPENAPI_BASE_URL legacy_environment: CHANJING_CONFIG_DIR, CHANJING_API_BASE machine_readable: manifest.yaml requires_ffmpeg: false requires_ffprobe: false --- # 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": [REDACTED_SECRET], "code": 0, "msg": "success", "data": { "access_token": [REDACTED_SECRET], "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": [REDACTED_SECRET], "screen_width": 1080, "screen_height": 1920, "callback": "https://example.com/openapi/callback", "model": 0, "audio_type": "tts", "tts_config": { "text": "君不见黄河之水天上来，奔流到海不复回。", "audio_man_id": [REDACTED_SECRET], "speed": 1, "pitch": 1 } } ``` Request body example (Audio-driven): ```json { "video_file_id": [REDACTED_SECRET], "screen_width": 1080, "screen_height": 1920, "model": 0, "audio_type": "audio", "audio_file_id": [REDACTED_SECRET] } ``` 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": [REDACTED_SECRET], "code": 0, "msg": "success", "data": [REDACTED_SECRET] } ``` 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": [REDACTED_SECRET], "code": 0, "msg": "success", "data": { "list": [ { "id": [REDACTED_SECRET], "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": [REDACTED_SECRET], "code": 0, "msg": "success", "data": { "id": [REDACTED_SECRET], "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": [REDACTED_SECRET], "code": 0, "msg": "success", "data": { "id": [REDACTED_SECRET], "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 [REDACTED_SECRET]) # 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 |


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (CRITICAL)