# 真人认证接口

> 真实人像素材的活体认证全流程 API：发起认证、H5 刷脸、查询结果、上传真人素材

要在视频中使用**真实人物形象**，本人必须先通过活体认证（刷脸），认证通过后系统自动创建一个 `LivenessFace` 素材组，此后即可向该组上传这位真人的照片并在视频生成中引用。整个流程全 API 化，无需人工审核介入。

<Info>
该流程用于防止深度伪造：只有完成刷脸的本人形象才能被用于生成，未经认证的真实人脸图片会被内容审核拒绝。
</Info>

## 鉴权方式

真人认证与 [素材库](/asset-management/asset-library) 共用同一入口，支持 API Key 和火山官方 AK/SK 两种鉴权方式。两种方式访问同一份账号素材数据，并受对应 API Key 的额度、状态、有效期和访问策略约束。

### API Key（Bearer）

```
POST https://api.looprouter.com/api/v3/assets?Action=<操作名>&Version=2024-01-01
Authorization: Bearer sk-...
```

### 火山官方 AK/SK（HMAC-SHA256）

使用 API Key 所绑定的 AK/SK，按照火山官方 `HMAC-SHA256` 方式签名。已有火山客户端只需将 Endpoint 替换为 `https://api.looprouter.com`，并使用 LoopRouter API Key 页面生成的 AK/SK；Action、Version、请求体和响应解析保持不变。

火山签名请求使用根路径 `/`，Service 为 `ark`，Region 推荐 `cn-beijing`。下面示例使用火山官方 Go SDK 发起真人认证会话：

```go
package main

import (
  "bytes"
  "io"
  "net/http"
  "os"

  "github.com/volcengine/volc-sdk-golang/base"
)

func main() {
  body := []byte(`{"Name":"主播小李","Description":"直播切片项目"}`)
  req, err := http.NewRequest(
    http.MethodPost,
    "https://api.looprouter.com/?Action=CreateVisualValidateSession&Version=2024-01-01",
    bytes.NewReader(body),
  )
  if err != nil {
    panic(err)
  }
  req.Header.Set("Content-Type", "application/json")

  credentials := base.Credentials{
    AccessKeyID:     os.Getenv("LOOPROUTER_AK"),
    SecretAccessKey: os.Getenv("LOOPROUTER_SK"),
    Region:          "cn-beijing",
    Service:         "ark",
  }
  req = credentials.Sign(req)

  resp, err := http.DefaultClient.Do(req)
  if err != nil {
    panic(err)
  }
  defer resp.Body.Close()
  io.Copy(os.Stdout, resp.Body)
}
```

<Note>
AK/SK 可用于 `CreateVisualValidateSession`、`GetVisualValidateResult` 及其他 JSON 素材 Action。后续视频生成接口仍使用 API Key；本地文件 `multipart/form-data` 上传也继续使用 API Key。
</Note>

## 认证流程

<Steps>
  <Step title="发起认证会话 — CreateVisualValidateSession">

```bash
curl -X POST "https://api.looprouter.com/api/v3/assets?Action=CreateVisualValidateSession&Version=2024-01-01" \
  -H "Authorization: Bearer $LOOPROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"Name": "主播小李", "Description": "直播切片项目"}'
```

响应：

```json
{
  "ResponseMetadata": { "RequestId": "...", "Action": "CreateVisualValidateSession", "Version": "2024-01-01", "Service": "ark" },
  "Result": {
    "BytedToken": "a1b2c3d4e5f6a7b8",
    "H5Link": "https://api.looprouter.com/api/portrait/visual-validation/go/a1b2c3d4e5f6a7b8",
    "ExpireTime": 1752941700000
  }
}
```

| 字段 | 说明 |
| --- | --- |
| `BytedToken` | 认证会话令牌，用于后续查询结果 |
| `H5Link` | 刷脸页面链接，**在手机浏览器中打开**（可将其生成二维码给被认证人扫码） |
| `ExpireTime` | 会话过期时间（毫秒时间戳），过期需重新发起 |

  </Step>
  <Step title="被认证人完成 H5 刷脸">
    将 `H5Link` 发给需要认证的本人，用手机打开并按提示完成人脸活体检测。会话有效期约 15 分钟。
  </Step>
  <Step title="查询认证结果 — GetVisualValidateResult">

```bash
curl -X POST "https://api.looprouter.com/api/v3/assets?Action=GetVisualValidateResult&Version=2024-01-01" \
  -H "Authorization: Bearer $LOOPROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"BytedToken": "a1b2c3d4e5f6a7b8"}'
```

三种结果：

**认证通过** — HTTP 200，返回真人素材组 ID：

```json
{ "Result": { "Status": "passed", "GroupId": "group-20260709185838-dcnvd" } }
```

**尚未完成** — HTTP 404，`Error.Code` 为 `NotFound.VisualValidateResult`。这不是异常，表示对方还没刷完脸，继续轮询即可（建议 3–5 秒一次）。

**失败 / 过期** — HTTP 200，`Result.Status` 为 `failed` 或 `expired`，失败时附带 `ResultCode` / `ResultMessage`。

  </Step>
  <Step title="向真人素材组上传照片 — CreateAsset">

```bash
curl -X POST "https://api.looprouter.com/api/v3/assets?Action=CreateAsset&Version=2024-01-01" \
  -H "Authorization: Bearer $LOOPROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "GroupId": "group-20260709185838-dcnvd",
    "Name": "小李-正面照",
    "URL": "https://example.com/xiaoli.jpg"
  }'
```

照片必须是**已认证本人**的清晰照片；上传其他人的照片会在内容审核阶段失败。随后用 `GetAsset` 轮询到 `Status: "Active"`。

  </Step>
  <Step title="在视频生成中引用真人素材">

```bash
curl -X POST "https://api.looprouter.com/api/v3/contents/generations/tasks" \
  -H "Authorization: Bearer $LOOPROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "doubao-seedance-2-0-260128",
    "content": [
      {"type": "text", "text": "图片1中的人物坐在书桌前，对镜头介绍产品：\"大家好，今天给大家带来一款新品\""},
      {"type": "image_url", "image_url": {"url": "asset://asset-20260709190143-ntwhb"}, "role": "reference_image"}
    ],
    "resolution": "720p",
    "duration": 8
  }'
```

  </Step>
</Steps>

## Python 完整示例

```python
import time
import requests

BASE = "https://api.looprouter.com/api/v3/assets"
HEADERS = {"Authorization": "Bearer sk-你的APIKey", "Accept-Encoding": "identity"}

def action(name, body):
    resp = requests.post(f"{BASE}?Action={name}&Version=2024-01-01", headers=HEADERS, json=body)
    return resp.status_code, resp.json()

# 1. 发起认证
_, data = action("CreateVisualValidateSession", {"Name": "主播小李"})
token = data["Result"]["BytedToken"]
print("请用手机打开完成刷脸:", data["Result"]["H5Link"])

# 2. 轮询认证结果（404 = 还没刷完，继续等）
while True:
    code, data = action("GetVisualValidateResult", {"BytedToken": token})
    if code == 404:
        time.sleep(5)
        continue
    status = data["Result"]["Status"]
    if status == "passed":
        group_id = data["Result"]["GroupId"]
        print("认证通过，素材组:", group_id)
        break
    raise SystemExit(f"认证未通过: {data['Result']}")

# 3. 上传真人照片并等待 Active
_, data = action("CreateAsset", {
    "GroupId": group_id,
    "Name": "小李-正面照",
    "URL": "https://example.com/xiaoli.jpg",
})
asset_id = data["Result"]["Id"]
while True:
    _, data = action("GetAsset", {"Id": asset_id})
    if data["Result"]["Status"] in ("Active", "Failed"):
        break
    time.sleep(3)
print("素材状态:", data["Result"]["Status"], "→ 生成请求中引用 asset://" + asset_id)
```

## 注意事项

<Warning>
- `BytedToken` 与素材组、素材 ID 一样属于敏感凭据，请勿泄露。
- 认证会话约 **15 分钟**过期，请在发起后尽快完成刷脸；过期后重新调用 `CreateVisualValidateSession` 即可。
- 一次认证对应一个真人素材组；同一账号可为多位真人分别发起认证，各自维护素材组。
</Warning>

<Tip>
生成效果建议：同一真人上传「正面全身照 + 自然表情面部特写」两张素材并同时引用；提示词中用「图片1」「图片2」指代，台词放在双引号内可获得更好的口播效果。
</Tip>

## 错误码

| HTTP | Code | 说明 |
| --- | --- | --- |
| 400 | `MissingParameter` | 缺少 `BytedToken` / `GroupId` / `URL` 等必填字段 |
| 404 | `NotFound.VisualValidateResult` | 认证尚未完成（轮询中的正常状态） |
| 404 | `NotFound` | 会话/素材组不存在或不属于当前账号 |
| 429 | `RateLimitExceeded` | 操作过于频繁，稍后重试 |
| 503 | `NoAvailableAssetChannel` | 当前账号的素材库服务暂未就绪，请联系我们开通 |

## 相关文档

<CardGroup cols={3}>
  <Card title="素材库 API" icon="images" href="/asset-management/asset-library">
    素材组与素材的完整管理接口
  </Card>
  <Card title="素材引用实战" icon="wand-magic-sparkles" href="/asset-management/asset-reference">
    从上传到生成的端到端示例
  </Card>
  <Card title="视频生成 API" icon="clapperboard" href="/api-capabilities/seedance2/video-generation">
    生成参数详解
  </Card>
</CardGroup>
