> ## Documentation Index
> Fetch the complete documentation index at: https://apidoc.cometapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hướng dẫn nhanh Sora 2 API: Tạo video với CometAPI

> Tạo một tác vụ video Sora 2 với CometAPI, thăm dò trạng thái và tải nội dung video đã hoàn thành bằng curl, Python hoặc Node.js.

## Những gì bạn sẽ xây dựng

Bạn sẽ gửi một tác vụ video Sora 2, lưu video ID được trả về, thăm dò cho đến khi tác vụ hoàn tất và tải nội dung video đã xử lý xong.

## Điều kiện tiên quyết

* Một API key CometAPI được lưu trong `COMETAPI_KEY`
* Python 3.10+ với `requests`, hoặc Node.js 18+
* Một worker phía máy chủ hoặc hàng đợi tác vụ để thăm dò

## API key, URL cơ sở, xác thực

Tạo tác vụ Sora bằng:

```text theme={null}
POST https://api.cometapi.com/v1/videos
```

Thăm dò trạng thái bằng:

```text theme={null}
GET https://api.cometapi.com/v1/videos/<video_id>
```

Tải nội dung đã hoàn thành bằng:

```text theme={null}
GET https://api.cometapi.com/v1/videos/<video_id>/content
```

Xác thực bằng Bearer token:

```text theme={null}
Authorization: Bearer $COMETAPI_KEY
```

## Ví dụ mã

Sử dụng các tab bên dưới để xem các ví dụ có thể sao chép bằng cURL, Python và Node.js.

<CodeGroup>
  ```bash cURL theme={null}
  curl https://api.cometapi.com/v1/videos \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    -F model=sora-2 \
    -F "prompt=A paper boat drifts across a calm pond at sunrise" \
    -F seconds=4 \
    -F size=1280x720

  curl "https://api.cometapi.com/v1/videos/<video_id>" \
    -H "Authorization: Bearer $COMETAPI_KEY"

  curl "https://api.cometapi.com/v1/videos/<video_id>/content" \
    -H "Authorization: Bearer $COMETAPI_KEY" \
    --output sora-result.mp4
  ```

  ```python Python theme={null}
  import os
  import time
  from pathlib import Path

  import requests

  api_key = os.environ["COMETAPI_KEY"]
  headers = {"Authorization": f"Bearer {api_key}"}

  create_response = requests.post(
      "https://api.cometapi.com/v1/videos",
      headers=headers,
      data={
          "model": "sora-2",
          "prompt": "A paper boat drifts across a calm pond at sunrise",
          "seconds": "4",
          "size": "1280x720",
      },
      timeout=60,
  )
  create_response.raise_for_status()
  video_id = create_response.json()["id"]

  for _ in range(60):
      status_response = requests.get(
          f"https://api.cometapi.com/v1/videos/{video_id}",
          headers=headers,
          timeout=30,
      )
      status_response.raise_for_status()
      status = status_response.json()
      if status["status"] == "completed":
          content_response = requests.get(
              f"https://api.cometapi.com/v1/videos/{video_id}/content",
              headers=headers,
              timeout=120,
          )
          content_response.raise_for_status()
          Path("sora-result.mp4").write_bytes(content_response.content)
          break
      if status["status"] == "failed":
          raise RuntimeError(status)
      time.sleep(5)
  else:
      raise TimeoutError("Sora job did not finish in time")
  ```

  ```javascript Node.js theme={null}
  import fs from "node:fs/promises";

  const form = new FormData();
  form.append("model", "sora-2");
  form.append("prompt", "A paper boat drifts across a calm pond at sunrise");
  form.append("seconds", "4");
  form.append("size", "1280x720");

  const createResponse = await fetch("https://api.cometapi.com/v1/videos", {
    method: "POST",
    headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },
    body: form,
  });

  if (!createResponse.ok) {
    throw new Error(await createResponse.text());
  }

  const { id } = await createResponse.json();

  for (let attempt = 0; attempt < 60; attempt += 1) {
    const statusResponse = await fetch(`https://api.cometapi.com/v1/videos/${id}`, {
      headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` },
    });

    if (!statusResponse.ok) {
      throw new Error(await statusResponse.text());
    }

    const status = await statusResponse.json();
    if (status.status === "completed") {
      const contentResponse = await fetch(
        `https://api.cometapi.com/v1/videos/${id}/content`,
        { headers: { Authorization: `Bearer ${process.env.COMETAPI_KEY}` } },
      );
      const videoBuffer = Buffer.from(await contentResponse.arrayBuffer());
      await fs.writeFile("sora-result.mp4", videoBuffer);
      break;
    }
    if (status.status === "failed") {
      throw new Error(JSON.stringify(status));
    }
    await new Promise((resolve) => setTimeout(resolve, 5000));
  }
  ```
</CodeGroup>

## Giải thích quy trình

Việc tạo Sora là bất đồng bộ. Endpoint tạo trả về một video ID và một trạng thái ban đầu. Hãy poll `GET /v1/videos/<video_id>` cho đến khi `status` là `completed` hoặc `failed`. Khi tác vụ hoàn tất, tải tệp xuống bằng `GET /v1/videos/<video_id>/content`.

Sử dụng chính xác kích thước `WxH`. Tài liệu tham chiếu API Sora mô tả các kích thước ngang và dọc tiêu chuẩn, cùng với các kích thước Pro lớn hơn cho quy trình làm việc của model Pro.

## Các tham số phổ biến

| Tham số           | Cách dùng                                                                       |
| ----------------- | ------------------------------------------------------------------------------- |
| `model`           | model ID của Sora. Ví dụ tham chiếu sử dụng `sora-2`.                           |
| `prompt`          | Prompt văn bản cho video.                                                       |
| `seconds`         | Thời lượng clip. Tài liệu tham chiếu API ghi nhận `4`, `8`, `12`, `16` và `20`. |
| `size`            | Kích thước đầu ra chính xác `WxH`, chẳng hạn như `1280x720` hoặc `720x1280`.    |
| `input_reference` | Tệp hình ảnh tham chiếu tùy chọn cho quy trình first-frame.                     |

## Khắc phục sự cố / Câu hỏi thường gặp

<AccordionGroup>
  <Accordion title="Yêu cầu tạo thất bại">
    Sử dụng multipart form data. Các yêu cầu tạo Sora trong tài liệu tham chiếu dùng các trường biểu mẫu, không phải phần thân JSON.
  </Accordion>

  <Accordion title="Tải xuống nội dung thất bại">
    Chỉ tải xuống nội dung sau khi endpoint trạng thái báo `completed`. Lưu trữ tệp hoàn tất trong hệ thống lưu trữ của riêng bạn.
  </Accordion>

  <Accordion title="Một kích thước Pro không hoạt động">
    Chỉ sử dụng các kích thước Pro lớn hơn với quy trình model Pro. Bắt đầu với `1280x720` cho yêu cầu đầu tiên.
  </Accordion>
</AccordionGroup>

## Các bước tiếp theo

* Đọc [Tài liệu tham chiếu API tạo video Sora 2](/api/video/sora-2/create).
* Thăm dò bằng [Truy xuất một video Sora 2](/api/video/sora-2/retrieve).
* Tải xuống bằng [Truy xuất nội dung video Sora 2](/api/video/sora-2/retrieve-content).
* Tìm các model video khả dụng trong [Models](/vi/overview/models).
* Xem lại [Sử dụng polling và webhooks cho việc tạo video](/vi/guides/webhook-and-polling-for-video-generation).
* Ước tính chi phí tác vụ với [Ước tính chi phí yêu cầu trước khi gọi model](/vi/guides/how-to-estimate-cost-before-calling-a-model).
