> This page is for Платформа, version V4 (default).
> For other versions, use one of these documentation indexes:
> - V4 (default): https://next.developer.frame.io/platform/v4/llms.txt
> - Версия 4 экспериментальная: https://next.developer.frame.io/platform/v4-experimental/llms.txt
> - Предыдущая версия: https://next.developer.frame.io/platform/v2/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://next.developer.frame.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://next.developer.frame.io/_mcp/server.

# SDK Frame.io для Python — руководство по добавлению файлов

В этом руководстве объясняется, как добавлять файлы в Frame.io с помощью **SDK Frame.io для Python** (`frameio`). SDK разбивает файлы на фрагменты и добавляет их частями в хранилище S3 через предварительно подписанные URL-адреса. При этом выполняются параллельные рабочие процессы, поддерживаются автоматические повторные попытки и предоставляется возможность отслеживать прогресс. Общие компоненты процесса добавлении файлов через API-интерфейс (URL-адреса для добавления, заголовки, разбиение на фрагменты) — в разделе [Как работает локальное и удаленное добавление файлов](./how-local-remote-uploads-work).

---

## Требования

#### Аутентификация

У вас есть рабочий клиент `Frameio`. Подробнее о настройке — в [руководстве по аутентификации](/platform/docs/guides/authentication/python-sdk).

#### Установка SDK

```bash
    pip install frameio
```

#### Целевая папка

Вам требуются идентификаторы `account_id` и `folder_id` папки, куда нужно добавить файл. Используйте SDK для их поиска.

```python
    # List your accounts
    accounts = client.accounts.index()
    account_id = accounts.data[0].id

    # List workspaces in the account
    workspaces = client.workspaces.index(account_id=account_id)
    workspace_id = workspaces.data[0].id

    # List projects in the workspace
    projects = client.projects.index(account_id=account_id, workspace_id=workspace_id)
    project = projects.data[0]

    # The project's root folder is the top-level upload target
    folder_id = project.root_folder_id

    # Or list subfolders to upload into a specific one
    folders = client.folders.list(account_id=account_id, folder_id=folder_id)
```

---

## Быстрый старт

```python
import os
from frameio import Frameio
from frameio.files import FileCreateLocalUploadParamsData
from frameio.upload import FrameioUploader

client = Frameio(token="YOUR_TOKEN")

file_path = "/path/to/video.mp4"
file_size = os.path.getsize(file_path)

# 1. Create the file resource and get pre-signed upload URLs
response = client.files.create_local_upload(
    account_id="YOUR_ACCOUNT_ID",
    folder_id="YOUR_FOLDER_ID",
    data=FileCreateLocalUploadParamsData(
        name="video.mp4",
        file_size=file_size,
    ),
)

# 2. Upload the file to S3
with open(file_path, "rb") as f:
    FrameioUploader(response.data, f).upload()
```

Готово. SDK разбивает файл на фрагменты на основе URL-адресов, полученных от API-интерфейса, добавляет их в хранилище в параллельном режиме и автоматически выполняет повторные попытки при сбоях.

---

## Как это работает

Локальное добавление — это двухэтапный процесс.

#### Создание ресурса для файла

Вызовите метод `client.files.create_local_upload()` с указанием имени и размера файла. API-интерфейс создает файл-заполнитель и возвращает предварительно подписанные URL-адреса S3 PUT — по одному на фрагмент. Количество URL-адресов (и, следовательно, фрагментов) зависит от размера файла.

#### Добавление в S3

Компонент `FrameioUploader` считывает полученные в ответе URL-адреса для добавления, разбивает ваш файл на соответствующие фрагменты и в параллельном режиме отправляет каждый фрагмент по его URL-адресу, используя пул потоков. Каждый такой запрос автоматически включает обязательные заголовки `x-amz-acl: private` и `Content-Type`.

> **Note**
>
> Добавление выполняется напрямую из вашего приложения в хранилище S3, минуя серверы API-интерфейса Frame.io. Аналогичную схему используют такие сервисы, как YouTube, Vimeo и Dropbox, для передачи больших файлов.

---

## Использование компонента `FrameioUploader`

`FrameioUploader` — это рекомендуемый инструмент для добавления файлов. Он служит оберткой для низкоуровневого механизма добавления файлов и управляет всеми процессами: извлекает URL-адреса из ответа API-интерфейса, добавляет нужные заголовки, разбивает файлы на фрагменты и выполняет их параллельную отправку.

### Отслеживание прогресса

Используйте функцию обратного вызова `on_progress` для отслеживания хода добавления.

```python
def on_progress(bytes_uploaded: int, total_bytes: int) -> None:
    pct = bytes_uploaded / total_bytes * 100
    print(f"\r{pct:.1f}% ({bytes_uploaded:,} / {total_bytes:,} bytes)", end="", flush=True)

with open(file_path, "rb") as f:
    FrameioUploader(response.data, f, on_progress=on_progress).upload()

print("\nUpload complete!")
```

Функция обратного вызова срабатывает после завершения отправки каждого фрагмента, отображая общее количество отправленных байтов и общий размер файла.

#### Индикатор выполнения на базе библиотеки Rich

Для создания эстетичного и информативного интерфейса в терминале используйте библиотеку [Rich](https://github.com/Textualize/rich).

```python
from rich.progress import Progress, BarColumn, DownloadColumn, TransferSpeedColumn, TimeRemainingColumn

with Progress(
    "[progress.description]{task.description}",
    BarColumn(),
    DownloadColumn(),
    TransferSpeedColumn(),
    TimeRemainingColumn(),
) as progress:
    task = progress.add_task("Uploading...", total=file_size)

    with open(file_path, "rb") as f:
        FrameioUploader(
            response.data, f,
            on_progress=lambda done, total: progress.update(task, completed=done),
        ).upload()
```

### Конфигурация

`FrameioUploader` принимает несколько дополнительных параметров.

| Параметр      | По умолчанию                                   | Описание                                                                                                              |
| ------------- | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `max_workers` | `5`                                            | Количество одновременных потоков добавления.                                                                          |
| `headers`     | `{&quot;x-amz-acl&quot;: &quot;private&quot;}` | Заголовки, отправляемые с каждым запросом S3 PUT. Пользовательские заголовки объединяются со значениями по умолчанию. |
| `max_retries` | `3`                                            | Количество повторных попыток для каждого фрагмента (экспоненциальная задержка: 1 с, 2 с, 4 с, ...).                   |
| `on_progress` | `Нет`                                          | Функция обратного вызова вида `(bytes_uploaded, total_bytes)`, срабатывающая после добавления каждого фрагмента.      |

```python
with open(file_path, "rb") as f:
    FrameioUploader(
        response.data,
        f,
        max_workers=10,       # more parallelism for high-bandwidth connections
        max_retries=5,        # more resilient on flaky networks
        on_progress=on_progress,
    ).upload()
```

### Полный пример

Полный пример кода с аутентификацией, добавлением файлов и отслеживанием прогресса.

```python
import os
from frameio import Frameio
from frameio.auth import ServerToServerAuth
from frameio.files import FileCreateLocalUploadParamsData
from frameio.upload import FrameioUploader

# Authenticate
auth = ServerToServerAuth(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
)
client = Frameio(token=auth.get_token)

# Prepare the file
file_path = "/path/to/video.mp4"
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)

# Create the file resource
response = client.files.create_local_upload(
    account_id="YOUR_ACCOUNT_ID",
    folder_id="YOUR_FOLDER_ID",
    data=FileCreateLocalUploadParamsData(
        name=file_name,
        file_size=file_size,
    ),
)

print(f"Uploading {file_name} ({file_size:,} bytes) in {len(response.data.upload_urls)} chunks...")

# Upload with progress
def on_progress(uploaded: int, total: int) -> None:
    print(f"\r{uploaded / total:.0%}", end="", flush=True)

with open(file_path, "rb") as f:
    FrameioUploader(response.data, f, on_progress=on_progress).upload()

print(f"\nDone! View at: {response.data.view_url}")
```

---

> **Tip**
>
> Если вам нужен полный контроль над процессом добавления, например, чтобы вручную разбивать файлы на фрагменты, выполнять интеграцию с асинхронными конвейерами или настраивать логику повторных попыток, обратитесь к разделу [Как работает локальное и удаленное добавление файлов](./how-local-remote-uploads-work), где описан прямой процесс работы с API-интерфейсом и приведен пример автономного сценария на Python.

---

## Удаленное добавление

Если файл доступен по публичному URL-адресу, используйте удаленное добавление. В этом случае разбиение на фрагменты не требуется — Frame.io получает файл напрямую.

```python
from frameio.files import FileCreateRemoteUploadParamsData

response = client.files.create_remote_upload(
    account_id="YOUR_ACCOUNT_ID",
    folder_id="YOUR_FOLDER_ID",
    data=FileCreateRemoteUploadParamsData(
        name="video.mp4",
        source_url="https://example.com/video.mp4",
    ),
)
print(f"File created: {response.data.id}")
```

> **Warning**
>
> В настоящее время для удаленного добавления установлено **ограничение на размер файла 50 ГБ**. Для файлов размером более 50 ГБ используйте [локальное добавление](#quick-start).

---

## Проверка статуса отправки

После завершения отправки можно убедиться, что файл был получен.

```python
status = client.files.show_file_upload_status(
    account_id="YOUR_ACCOUNT_ID",
    file_id=response.data.id,
)
print(f"Upload complete: {status.data.upload_complete}")
```