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

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


Требования

1

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

У вас есть рабочий клиент Frameio. Подробнее о настройке — в руководстве по аутентификации.

2

Установка SDK

pip install frameio
3

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

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

# 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)

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

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-интерфейса, добавляет их в хранилище в параллельном режиме и автоматически выполняет повторные попытки при сбоях.


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

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

1

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

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

2

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

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

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


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

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

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

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

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.

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_workers5Количество одновременных потоков добавления.
headers{"x-amz-acl": "private"}Заголовки, отправляемые с каждым запросом S3 PUT. Пользовательские заголовки объединяются со значениями по умолчанию.
max_retries3Количество повторных попыток для каждого фрагмента (экспоненциальная задержка: 1 с, 2 с, 4 с, …).
on_progressНетФункция обратного вызова вида (bytes_uploaded, total_bytes), срабатывающая после добавления каждого фрагмента.
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()

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

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

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}")

Если вам нужен полный контроль над процессом добавления, например, чтобы вручную разбивать файлы на фрагменты, выполнять интеграцию с асинхронными конвейерами или настраивать логику повторных попыток, обратитесь к разделу Как работает локальное и удаленное добавление файлов, где описан прямой процесс работы с API-интерфейсом и приведен пример автономного сценария на Python.


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

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

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}")

В настоящее время для удаленного добавления установлено ограничение на размер файла 50 ГБ. Для файлов размером более 50 ГБ используйте локальное добавление.


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

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

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}")