# 素材库

URL: http://localhost:3000/docs/zh-cn/api/asset-library

素材库是一组火山（Volcengine）风格的 RPC 接口，用于管理生成视频时可复用的输入素材（图片 / 视频 / 音频）与虚拟人像、真人素材。本文介绍接入信息、鉴权、请求与响应约定，以及各接口的入口。



素材库管理生成视频时可复用的输入素材：图片、视频、音频，以及虚拟人像、真人素材。素材 ID 即[创建视频生成任务](/zh-cn/api/createSeedanceTask)中 `asset://<ASSET_ID>` 引用的对象。

接口为火山（Volcengine）RPC 风格：单一接入点、以 `?Action=` 区分接口、AK/SK + SigV4 签名，可直接用火山官方 SDK 调用（替换 AK/SK 与接入点即可）。

## 接入信息 [#接入信息]

| 项           | 值                              |
| ----------- | ------------------------------ |
| 接入点（Host）   | `maas-ark.stringx.top`         |
| 请求路径        | `/`（根路径，靠 `?Action=` 区分接口）     |
| 方法          | 一律 `POST`，请求体为 JSON            |
| Region      | `cn-beijing`                   |
| Service     | `ark`                          |
| API Version | `2024-01-01`                   |
| 鉴权          | Access Key（AK/SK）+ 火山 SigV4 签名 |

所有接口都形如：

```text
POST https://maas-ark.stringx.top/?Action=<接口名>&Version=2024-01-01
Content-Type: application/json

{ …请求体… }
```

## 响应结构 [#响应结构]

所有接口的返回体都是同一层结构，成功和失败只差一个 `Error` 字段：

```json
{
  "ResponseMetadata": {
    "RequestId": "…",
    "Action": "…",
    "Version": "2024-01-01",
    "Service": "ark",
    "Region": "cn-beijing",
    "Error": { "CodeN": 0, "Code": "…", "Message": "…" }
  },
  "Result": { }
}
```

* 判断成败：看 `ResponseMetadata.Error` 是否存在。存在即失败，`Code` 是错误码；成功时没有该字段，业务数据在 `Result` 里。
* `RequestId` 便于排查问题，反馈时请一并附上。

## 鉴权（AK/SK + SigV4） [#鉴权aksk--sigv4]

AK / SK 在控制台 **计费管理 → 令牌管理 → 访问密钥** 创建。请求以火山 SigV4 签名，推荐用官方 SDK 完成（见 [SDK 初始化](#sdk-初始化)），无需手写。

自行实现签名时，密钥派生**不带 `AWS4` 前缀**，凭证范围（CredentialScope）结尾固定为 `request`。

<Callout type="warn" title="暂不支持 STS 临时凭证">
  本服务只接受长期 AK/SK。带 `X-Security-Token` 的请求会返回 `InvalidSecretToken`。请使用长期 AK/SK 调用。
</Callout>

## 项目（ProjectName） [#项目projectname]

所有接口接受可选参数 `ProjectName`，默认 `default`，按请求选择资源所属项目：

* 不传或传 `default` → 默认项目。
* 不存在的项目名 → `NotFound.project`。
* 无成员权限的项目 → `AccessDenied`。

## 素材组类型（GroupType） [#素材组类型grouptype]

素材归属于素材组，素材组分两类：

| GroupType      | 含义            | 创建方式                                                                                                                                                                                         |
| -------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `AIGC`         | 虚拟人像等 AIGC 素材 | 可通过 [CreateAssetGroup](/zh-cn/api/asset-library/CreateAssetGroup) 用 API 创建                                                                                                                   |
| `LivenessFace` | 真人素材          | 真人素材的认证会话可通过 [CreateVisualValidateSession](/zh-cn/api/asset-library/CreateVisualValidateSession) 拉起、用 [GetVisualValidateResult](/zh-cn/api/asset-library/GetVisualValidateResult) 取回其素材组 ID。 |

## 素材状态（Status） [#素材状态status]

素材对外只有三种状态：

| Status       | 含义                    |
| ------------ | --------------------- |
| `Processing` | 处理中，尚不可用              |
| `Active`     | 处理完毕，可用               |
| `Failed`     | 处理失败，原因见 `Error.Code` |

## 上传素材的流程 [#上传素材的流程]

[CreateAsset](/zh-cn/api/asset-library/CreateAsset) 是**异步**接口，只接受**公网可访问的 URL**，不支持文件直传 / Base64。上传分两步：

1. 将文件放至对象存储（如火山 TOS），得到可下载的 URL——公开读的桶用公网地址 `https://{bucket}.{endpoint}/{key}`，私有读的桶用有时效的预签名 GET URL。
2. 以该 URL 调 `CreateAsset` 入库，用返回的 `Id` 轮询 [GetAsset](/zh-cn/api/asset-library/GetAsset) / [ListAssets](/zh-cn/api/asset-library/ListAssets)，直到 `Status` 为 `Active`（可用）或 `Failed`（失败）。

`ListAssets` / `GetAsset` 返回的 `URL` 为重新托管的签名地址，**有效期 12 小时**，需及时转存。

## SDK 初始化 [#sdk-初始化]

各语言均以「初始化客户端 → 调用 `ListAssetGroups`」为例，其余接口替换 `Action` 与请求体即可。

### Node.js [#nodejs]

```bash
npm i @volcengine/openapi
```

```js
import { Service } from '@volcengine/openapi';

const ark = new Service({
  host: 'maas-ark.stringx.top',
  region: 'cn-beijing',
  serviceName: 'ark',
  defaultVersion: '2024-01-01',
  accessKeyId: process.env.VOLC_ACCESS_KEY,
  secretKey: process.env.VOLC_SECRET_KEY,
});

const listAssetGroups = ark.createJSONAPI('ListAssetGroups');
const res = await listAssetGroups({
  Filter: { GroupType: 'AIGC' },
  PageNumber: 1,
  PageSize: 10,
  ProjectName: 'default',
});
if (res.ResponseMetadata.Error) {
  throw new Error(`${res.ResponseMetadata.Error.Code}: ${res.ResponseMetadata.Error.Message}`);
}
console.log(res.Result.Items);
```

### Python [#python]

```bash
pip install volcengine
```

```python
import json
from volcengine.base.Service import Service
from volcengine.ServiceInfo import ServiceInfo
from volcengine.ApiInfo import ApiInfo
from volcengine.Credentials import Credentials

AK, SK = "your-ak", "your-sk"

service_info = ServiceInfo(
    "maas-ark.stringx.top",
    {"Accept": "application/json"},
    Credentials(AK, SK, "ark", "cn-beijing"),
    5, 5, "https",
)
api_info = {
    name: ApiInfo("POST", "/", {"Action": name, "Version": "2024-01-01"}, {}, {})
    for name in ["ListAssetGroups", "CreateAssetGroup", "CreateAsset", "GetAsset"]
}

class ArkService(Service):
    def __init__(self):
        super().__init__(service_info, api_info)

svc = ArkService()
svc.set_ak(AK)
svc.set_sk(SK)

resp = svc.json("ListAssetGroups", {}, json.dumps({
    "Filter": {"GroupType": "AIGC"},
    "PageNumber": 1, "PageSize": 10, "ProjectName": "default",
}))
print(resp)
```

### Golang [#golang]

```bash
go get github.com/volcengine/volc-sdk-golang
```

```go
serviceInfo := &base.ServiceInfo{
    Timeout: 5 * time.Second,
    Host:    "maas-ark.stringx.top",
    Scheme:  "https",
    Header:  http.Header{"Accept": []string{"application/json"}},
    Credentials: base.Credentials{Region: "cn-beijing", Service: "ark"},
}
mk := func(action string) *base.ApiInfo {
    return &base.ApiInfo{
        Method: http.MethodPost,
        Path:   "/",
        Query:  url.Values{"Action": {action}, "Version": {"2024-01-01"}},
    }
}
client := base.NewClient(serviceInfo, map[string]*base.ApiInfo{
    "ListAssetGroups": mk("ListAssetGroups"),
})
client.SetAccessKey("your-ak")
client.SetSecretKey("your-sk")

body, _ := json.Marshal(map[string]any{
    "Filter": map[string]string{"GroupType": "AIGC"}, "PageNumber": 1, "PageSize": 10,
})
resp, code, err := client.CtxJson(context.Background(), "ListAssetGroups", url.Values{}, string(body))
fmt.Println(code, string(resp), err)
```

## 接口一览 [#接口一览]

| 分类   | Action                                                                              | 说明                 |
| ---- | ----------------------------------------------------------------------------------- | ------------------ |
| 素材组  | [CreateAssetGroup](/zh-cn/api/asset-library/CreateAssetGroup)                       | 创建素材组（仅 AIGC）      |
|      | [ListAssetGroups](/zh-cn/api/asset-library/ListAssetGroups)                         | 查询素材组列表            |
|      | [GetAssetGroup](/zh-cn/api/asset-library/GetAssetGroup)                             | 查询单个素材组            |
|      | [UpdateAssetGroup](/zh-cn/api/asset-library/UpdateAssetGroup)                       | 更新名称 / 描述          |
|      | [DeleteAssetGroup](/zh-cn/api/asset-library/DeleteAssetGroup)                       | 删除组（连同组内素材，不可逆）    |
| 素材   | [CreateAsset](/zh-cn/api/asset-library/CreateAsset)                                 | 创建素材（传公网 URL，异步入库） |
|      | [ListAssets](/zh-cn/api/asset-library/ListAssets)                                   | 查询素材列表             |
|      | [GetAsset](/zh-cn/api/asset-library/GetAsset)                                       | 查询单个素材（确认 Status）  |
|      | [UpdateAsset](/zh-cn/api/asset-library/UpdateAsset)                                 | 更新素材名称             |
|      | [DeleteAsset](/zh-cn/api/asset-library/DeleteAsset)                                 | 删除素材               |
| 真人素材 | [CreateVisualValidateSession](/zh-cn/api/asset-library/CreateVisualValidateSession) | 拉起端上 H5 真人认证       |
|      | [GetVisualValidateResult](/zh-cn/api/asset-library/GetVisualValidateResult)         | 取回认证生成的素材组 ID      |

## 错误码 [#错误码]

错误分两层：

**网关 / 签名层**（带数字 `CodeN`）：

| Code                     | 含义                                                              |
| ------------------------ | --------------------------------------------------------------- |
| `SignatureDoesNotMatch`  | 签名不匹配。建议用官方 SDK 签名；检查 AK/SK、region（`cn-beijing`）、service（`ark`） |
| `InvalidAccessKey`       | AK 不合法                                                          |
| `InvalidAuthorization`   | 缺少 / 格式错误的 `Authorization` 头                                    |
| `InvalidSecretToken`     | 使用了 STS 临时凭证（不支持）                                               |
| `MissingParameter`       | 缺少 `Action` / `Version` 等必填参数                                   |
| `InvalidActionOrVersion` | `Action` 未知或 `Version` 不受支持                                     |
| `FlowLimitExceeded`      | 超出限速（429），降低 QPS                                                |

**业务层**（`CodeN` 为 0）：

| Code                             | 含义                     |
| -------------------------------- | ---------------------- |
| `MissingParameter.<参数>`          | 缺少某个业务参数               |
| `InvalidParameter.<参数>`          | 某个业务参数非法（枚举 / 长度 / 范围） |
| `NotFound` / `NotFound.<资源>`     | 资源不存在或无权访问             |
| `AccessDenied`                   | 无该项目成员权限               |
| `OperationDenied.ServiceNotOpen` | 租户未开通素材库能力             |
| `OperationDenied.InvalidState`   | 资源当前状态不允许该操作           |

此外，素材失败时其 `Error.Code`（见 `GetAsset`）取值如 `DownloadFailed`、`TypeMismatch`、`FormatUnsupported`、`FileSizeTooLarge` 等。

## 与火山官方的差异 [#与火山官方的差异]

照火山官方文档 / SDK 接入时，注意以下差异：

* **不支持 STS 临时凭证**：只接受长期 AK/SK，带 `X-Security-Token` 会被拒（`InvalidSecretToken`）。
* **需要开通**：租户未开通素材库能力时返回 `OperationDenied.ServiceNotOpen`。
* **参数级错误码**：`MissingParameter.<参数>` / `InvalidParameter.<参数>` 这类细分后缀按本服务约定，可能与火山返回的不完全逐字一致（响应结构与通用码一致）。

## 官方文档 [#官方文档]

本服务的接口沿用火山方舟素材库，完整的官方使用指南见：

* [私域虚拟人像素材资产库使用指南](https://docs.volcengine.com/docs/82379/2333565?lang=zh\&redirect=1)（`AIGC` 虚拟人像）
* [私域真人人像素材资产使用指南](https://docs.volcengine.com/docs/82379/2333589?redirect=1\&lang=zh#5e19b7f1)（`LivenessFace` 真人素材）
