> This page is for С камеры в облако.

> 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.

# Практическое руководство: добавление (в реальном времени)

## Введение





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





API-интерфейс добавления в режиме реального времени позволяет воспроизводить ресурсы в Frame.io всего через несколько секунд после завершения записи, что значительно повышает эффективность технологического процесса.





## Демонстрационное видео

Краткий обзор этой функции есть в [демонстрационном видео](https://f.io/qjwfGmTa). В видео показано добавление рендера из Adobe Media Encoder в режиме реального времени, при этом видео можно воспроизвести в Frame.io всего через 5 секунд после завершения рендеринга.

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

Если вы еще не сделали этого, прочитайте руководство [Реализация C2C: настройка](./implementing-c2c-setting-up). Вам понадобится `access_token`, полученный [в процессе аутентификации и авторизации](./implementing-c2c-authentication-and-authorization). Мы будем использовать в наших примерах тот же [тестовый ресурс](https://f.io/Rq1q5CzB) из руководства по базовому добавлению. Рекомендуем ознакомиться с [руководством по базовому добавлению](./how-to-basic-upload), поскольку мы будем использовать понятия и принципы, которые там объясняются.

## Создание ресурса в режиме реального времени

Добавления в режиме реального времени начинаются с создания измененного ресурса. При создании ресурса установите для параметра `is_realtime_upload` значение `true` и не указывайте параметр `filesize` (или установите для него значение `null`), поскольку окончательный размер во время создания неизвестен:

```shell
{
curl -X POST https://api.frame.io/v2/devices/assets \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "name": "C2C_TEST_CLIP.mp4", 
            "filetype": "video/mp4", 
            "is_realtime_upload": true
        }
__JSON__
} | python -m json.tool
```




<Info title="Спецификация конечной точки API-интерфейса">
  Документацию для `/v2/devices/assets` можно [найти здесь](/camera-to-cloud/api-reference/device-asset-create).
</Info>

<Warning title="Расширение и имя файла">
  Для ресурсов в режиме реального времени требуется расширение файла. Если при создании ресурса имя файла неизвестно, можно использовать поле `extension` (формат: `'.mp4'`). Рекомендуем этот способ, если вы планируете обновить название ресурса позже.
</Warning>


Ответ для ресурсов в режиме реального времени упрощен по сравнению со стандартным созданием ресурса:





```json
{
    "id": "{asset_id}",
    "name": "C2C_TEST_CLIP.mp4"
}
```

Обратите внимание, что `upload_urls` отсутствует — для добавлений в режиме реального времени мы будем создавать URL-адреса добавления по требованию по мере создания файла.

## Запрос URL-адресов добавления

Запрашиваем URL-адрес для первой половины нашего файла (10 568 125 байт), используя `asset_id` из предыдущего ответа:

```shell
{
curl -X POST https://api.frame.io/v2/devices/assets/{asset_id}/realtime_upload/parts \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "parts": [
                {
                    "number": 1,
                    "size": 10568125,
                    "is_final": false
                }
            ]
        }
__JSON__
} | python -m json.tool
```




<Info title="Спецификация конечной точки API-интерфейса">
  Документацию для `/v2/devices/assets/{asset_id}/realtime_upload/parts` можно [найти здесь](/camera-to-cloud/api-reference/device-create-realtime-upload-parts).
</Info>


Описание параметров запроса:




* `parts`: список фрагментов добавления, для которых нужны URL. Запрос нескольких URL в одном вызове повышает эффективность.

* `number`: порядковый номер фрагмента, начиная с 1. Номера можно пропускать, а фрагменты добавлять в любом порядке, но собираться они будут последовательно. Не может превышать 10 000 (ограничение AWS). * `size`: размер фрагмента в байтах. Должен соответствовать [ограничениям многочастного добавления AWS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html). * `is_final`: указывает, является ли этот фрагмент последним фрагментом файла.

Ответ содержит запрашиваемые URL добавления:





```json
{
    "upload_urls": [
        "https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_01_path]"
    ]
}
```

Список `upload_urls` напрямую соответствует порядку запроса `parts`.

Теперь добавьте первый фрагмент, как описано в руководстве по базовому добавлению:





```shell
head -c 10568125 ~/Downloads/C2C_TEST_CLIP.mp4 | \
curl -X PUT https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_01_path] \
        --include \
        --header 'content-type: video/mp4' \
        --header 'x-amz-acl: private' \
        --data-binary @-
```





Затем запросите URL для второго и последнего фрагмента:





```shell
{
curl -X POST https://api.frame.io/v2/devices/assets/{asset_id}/realtime_upload/parts \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "asset_filesize": 21136250,
            "parts": [
                {
                    "number": 2,
                    "size": 10568125,
                    "is_final": true
                }
            ]
        }
__JSON__
} | python -m json.tool
```





Обратите внимание на важные дополнения:




* для параметра `is_final` установлено значение `true` для последнего фрагмента, которое показывает, что после этого добавление будет завершено;
* `asset_filesize` указывает общий размер файла. Эта информация требуется, когда любой фрагмент имеет параметр `is_final: true`.




После получения URL-адреса в ответе:





```json
{
    "upload_urls": [
        "https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_02_path]"
    ]
}
```





Добавьте последний фрагмент:





```shell
tail -c 10568125 ~/Downloads/C2C_TEST_CLIP.mp4 | \
curl -X PUT https://frameio-uploads-production.s3-accelerate.amazonaws.com/parts/[part_02_path] \
        --include \
        --header 'content-type: video/mp4' \
        --header 'x-amz-acl: private' \
        --data-binary @-
```




<Warning title="Обработка последнего фрагмента">
  


Когда последний фрагмент добавлен, Frame.io начинает сборку полного файла. Этот процесс включает 60-секундный резервный период для завершения добавления любых оставшихся фрагментов. Рекомендуем добавлять последний фрагмент только после успешного добавления всех остальных фрагментов.



</Warning>


Вот и все! Перейдя на Frame.io, вы увидите успешно добавленный ресурс в реальном времени. 🎉





## Управление именами ресурсов

Если при создании ресурса имя файла неизвестно, вы можете использовать поле `расширение` без `имени`:

```shell
{
curl -X POST https://api.frame.io/v2/devices/assets \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "extension": ".mp4", 
            "filetype": "video/mp4", 
            "is_realtime_upload": true
        }
__JSON__
} | python -m json.tool
```





Система назначит имя по умолчанию:





```json
{
    "id": "{asset_id}",
    "name": "[new file].mp4"
}
```

Вы можете обновить это имя, включив поле `asset_name` при запросе URL-адресов для добавления:

```shell
{
curl -X POST https://api.frame.io/v2/devices/assets/{asset_id}/realtime_upload/parts \
    --header 'Authorization: Bearer [access_token]' \
    --header 'Content-Type: application/json' \
    --header 'x-client-version: 2.0.0' \
    --data-binary @- <<'__JSON__' 
        {
            "asset_name": "C2C_TEST_CLIP.mp4",
            "asset_filesize": 21136250,
            "parts": [
                {
                    "number": 2,
                    "size": 10568125,
                    "is_final": true
                }
            ]
        }
__JSON__
} | python -m json.tool
```





Имя будет обновлено только в том случае, если ресурс все еще использует имя, присвоенное по умолчанию; если он был переименован в интерфейсе Frame.io или имя уже было изменено, запрос будет проигнорирован.





## Оптимизация запросов URL





Для повышения эффективности запрашивайте URL-адреса для всех фрагментов, для которых у вас есть доступные данные, сразу, а не по отдельности. Это особенно важно для больших файлов, где скорость добавления может отставать от создания данных.





## Обработка заголовков медиафайлов





Некоторые медиаформаты требуют заголовка в начале файла, которые записываются только после завершения всего файла. Это создает проблему, когда заголовок меньше минимального размера фрагмента AWS в 5 МиБ (5 242 880 байт).





Что мы рекомендуем:




1. Зарезервируйте первые 5 242 880 байт медиаданных без добавления.
2. Начинайте добавление фрагментов с `part_number=2`.
3. Когда файл будет завершен, добавьте шапку к зарезервированным данным.
4. Запросите URL для `part_number=1` и добавьте этот объединенный фрагмент.





Это гарантирует, что первый фрагмент будет соответствовать требованиям к минимальному размеру, и при этом сохранится правильная структура файла.





## Масштабирование размера фрагментов для оптимизации производительности





AWS устанавливает ограничения, которые влияют на стратегию добавления:



* максимальный размер файла: 5 ТиБ (5 497 558 138 880 байт);
* максимальное количество фрагментов: 10 000;
* минимальный размер фрагмента: 5 МиБ (5 242 880 байт).




Фиксированный размер фрагмента накладывает ограничения:



* если все 10 000 фрагментов имеют минимальный размер (5 МиБ), общий размер файла будет не больше ~52,4 ГБ
* При равномерном распределении файла максимального размера блоки будут иметь размер ~550 МБ — слишком большой для эффективной потоковой передачи файлов меньшего размера.




Нам нужно сбалансировать эти ограничения: с одной стороны, обеспечить небольшие фрагменты для гибкого добавления, с другой — гарантировать, что при необходимости мы сможем обработать очень большие файлы.





### Рекомендуемая формула размера фрагмента





Вот предлагаемый подход в Python:





**`Python`**

```python title="Python"
import math
from typing import Callable

# Constants
MINIMUM_PART_SIZE = 5_242_880
MAXIMUM_PART_COUNT = 10_000
MAXIMUM_FILE_SIZE = 5_497_558_138_880

# Maximum uniform data rate that allows for 10,000 parts
MAXIMUM_DATA_RATE = MAXIMUM_FILE_SIZE // MAXIMUM_PART_COUNT

def part_size(part_number: int, format_bytes_per_second: int) -> int:
    """
    Returns the payload size for a specific part number given the file's
    expected data rate.
    """
    if part_number < 1:
        raise ValueError("part_number must be greater than 0")

    if part_number > 10_000:
        raise ValueError("part_number must be less than 10,000")

    # Make sure we never go above the maximum data rate or fall below the
    # minimum part size, even if the data rate is lower.
    data_rate = min(format_bytes_per_second, MAXIMUM_DATA_RATE)
    data_rate = max(data_rate, MINIMUM_PART_SIZE)

    # Calculate a scalar given our data rate. We will explain this step
    # futher on in the guides.
    scalar = -(2 * (125 * data_rate - 68_719_476_736)) / 8_334_583_375
    part_size = math.floor(scalar * pow(part_number, 2)) + data_rate

    return part_size

```

... где `part_number` имеет значение от `1` до `10_000` включительно, а `format_bytes_per_second` — это ожидаемое среднее количество байтов, которое ваш файл должен потреблять в секунду. О том, как была получена формула, — [ниже](/camera-to-cloud/how-to-upload-realtime#showing-our-work).
<Info title="Значение переменной scalar">
  Переменная `scalar` и расчет могут показаться немного запутанными на первый взгляд, но это математический инструмент, который гарантирует, что, независимо от значения, которое мы используем для `format_bytes_per_second`, если мы введем в функцию все допустимые значения `part_number` от `1` до `10_0000`, то получим набор значений, общая сумма которых составит *точно* наш лимит размера файла 5 ТиБ — настолько точно, насколько это возможно. Ниже мы [показываем](/camera-to-cloud/how-to-upload-realtime#showing-our-work), как мы пришли к этой формуле.
</Info>

<Info title="Округление до меньшего">
  


Используя округление до меньшего, мы оставляем некоторые байты неиспользованными, но гарантируем, что обычное округление более 10 000 фрагментов не приведет случайно к превышению максимально допустимого размера файла. В худшем случае 10 000 байтов, то есть 10 КБ, останутся неиспользованными — это приемлемый компромисс.



</Info>


Важные характеристики этой формулы:




* при добавлении 10 000 фрагментов общий объем загружаемых данных будет отличаться от предельного размера файла (5 ТиБ) максимум на 10 КБ;
* оптимизация за счет размещения меньших, более эффективных полезных нагрузок в начале для улучшения отклика при добавлении коротких и средних клипов;
* у очень длинных клипов время между окончанием записи файла и возможностью его воспроизведения будет больше.




Недостатки третьего пункта компенсируются вторым пунктом и тем, что большинство клипов не достигнет размера, при котором третий пункт сыграет свою роль. Мы обеспечиваем быстрый отклик для *БОЛЬШИНСТВА*, соглашаясь на медленный отклик для очень немногих.

Более продвинутая и эффективная версия нашей формулы (которая создает анонимную функцию `part_size_calculator` с предварительно вычисленными и встроенными статическими скалярными значениями и скоростью данных) может выглядеть так:

**`Python`**

```python title="Python"
def create_part_size_calculator(format_bytes_per_second: int) -> Callable[[int], int]:
    """
    Returns a function that takes in a `part_number` and returns a
    `part_size` based on `data_rate`.
    """

    # Make sure we never go above the maximum data rate or fall below the
    # minimum part size, even if the data rate is lower.
    data_rate = min(format_bytes_per_second, MAXIMUM_DATA_RATE)
    data_rate = max(data_rate, MINIMUM_PART_SIZE)

    static_scalar = -(2 * (125 * data_rate - 68_719_476_736)) / 8_334_583_375

    def part_size_calculator(part_number: int) -> int:
        """Calculates size in bytes of upload for `part_number`."""
        if part_number < 1:
            raise ValueError("part_number must be greater than 0")

        if part_number > 10_000:
            raise ValueError("part_number must be less than 10,000")

        return math.floor(static_scalar * pow(part_number, 2) + data_rate)

    return part_size_calculator

```





### Как работает формула.





Рассмотрим результаты вычислений, полученных с помощью приведенной выше формулы, для нескольких распространенных типов файлов.

**Пример 1**: веб-формат

Для форматов, воспроизводимых в веб-среде, со скоростью не более ~5,3 МБ/с (большинство файлов H.264/H.265/HEVC) мы получим следующую прогрессию размера полезной нагрузки:




| Всего фрагментов | Байты полезной нагрузки | МБ полезной нагрузки | Всего байт файла | Всего ГБ файла |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 5 242 896 | 5,2 МБ | 5 242 896 | 0,0 ГБ |
| 1000 | 21 575 817 | 21,6 МБ | 10 695 361 357 | 10,7 ГБ |
| 5000 | 413 566 329 | 413,6 МБ | 706 957 655 928 | 707,0 ГБ |
| 10 000 | 1 638 536 679 | 1638,5 МБ | 5 497 558 133 921 | 5497,6 ГБ |
**Расшифровка столбцов таблицы** — `Всего фрагментов`: общее количество фрагментов файла, добавленных в AWS. — `Байты полезной нагрузки`: размер полезной нагрузки AWS PUT, когда значение `part_number` равно значению в столбце `Всего фрагментов`. — `МБ полезной нагрузки`: то же, что `Байты полезной нагрузки`, но в мегабайтах. — `Всего байт файла`: общее количество байт, добавленных для файла, когда добавлено число последовательных фрагментов, указанное в столбце `Всего фрагментов`. — `Всего ГБ файла`: то же, что `Всего байт файла`, но в ГБ.

Эти значения хорошо сбалансированы для добавления в режиме реального времени, особенно для кодеков веб-воспроизведения, таких как H.264; большинство будет менее 10,7 ГБ и поэтому потребует не более 1000 фрагментов. Ожидается, что размер полезной нагрузки никогда не превысит 21,6 МБ.





Если мы обработаем даже половину наших фрагментов, размер полезной нагрузки все равно никогда не превысит 413,5 МБ. Общий размер добавления составит 707 ГБ, что более чем достаточно для подавляющего большинства веб-файлов.





Только когда разрешенное количество фрагментов начинает заканчиваться, размер файла будет увеличиваться. Однако он никогда не превышает 1,7 ГБ, что значительно ниже лимита AWS в 5 ГиБ на часть.

**Пример 2**. Prores 422 LT Prores 422 LT [имеет скорость передачи данных 102 Мбит/с](https://www.wolframalpha.com/input?i=-%282+%28-68%2C719%2C476%2C736+%2B+125+12%2C750%2C000%29%29%2F8%2C334%2C583%2C375) и создает следующую таблицу:
| Всего фрагментов | Байты полезной нагрузки | МБ полезной нагрузки | Всего байт файла | Всего ГБ файла |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 12 750 016 | 12,8 МБ | 12 750 016 | 0,0 ГБ |
| 1000 | 28 857 758 | 28,9 МБ | 18 127 308 783 | 18,1 ГБ |
| 5 000 | 415 443 954 | 415,4 МБ | 735 107 948 432 | 735,1 ГБ |
| 10 000 | 1 623 525 817 | 1623,5 МБ | 5 497 558 133 958 | 5497,6 ГБ |




В этой таблице показаны полезные свойства по сравнению с нашей формулой, оптимизированной для веб-среды. В первых 1000 фрагментах мы можем добавить на 8 ГБ больше файлов. Большие полезные нагрузки в начале означают, что нам не нужно будет слишком быстро запрашивать URL-адреса в начале. В результате добавление идет эффективнее при более высокой скорости передачи данных. Размер полезной нагрузки в конце процесса добавления остается большим.

**Пример 2**. Camera Raw

Теперь попробуем формат RAW со скоростью передачи данных 280 МБ/с. При такой быстрой передаче данных попытка добавления фрагментами по 5 МиБ в начале просто не имеет смысла.




| Всего фрагментов | Байты полезной нагрузки | МБ полезной нагрузки | Всего байт файла | Всего ГБ файла |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 280 000 008 | 280,0 МБ | 280 000 008 | 0,3 ГБ |
| 1000 | 288 091 460 | 288,1 МБ | 282 701 200 139 | 282,7 ГБ |
| 5000 | 482 286 516 | 482,3 МБ | 1 737 245 341 542 | 1737,2 ГБ |
| 10 000 | 1 089 146 065 | 1089,1 МБ | 5 497 558 133 870 | 5497,6 ГБ |




Ранние полезные нагрузки не только более эффективны, но и позволяют сэкономить более половины гигабайта ближе к концу, так что эти сетевые вызовы менее восприимчивы к перебоям в работе сети.





### Какую работу мы проделали





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





Нам нужна была формула, которая откладывала бы большие, более тяжелые полезные нагрузки на более поздние разрешенные фрагменты — до которых в большинстве добавлений дело не дойдет, — а более легкие и эффективные полезные нагрузки размещала бы в начале, где каждое добавление имеет преимущество. В то же время нужно было гарантировать, что алгоритм попадет в диапазон ограничений размера файла (5 ТиБ) *точно на* фрагменте номер 10 000.





На этом этапе в игру вступил математический анализ.





Чтобы график рос экспоненциально, формула должна выглядеть примерно так:





```math
n^2
```

... где `n` — номер фрагмента. Кроме того, нужно, чтобы каждый фрагмент равнялся как минимум скорости передачи данных для нашей формулы, которую мы обозначим `r`:

```math
n^2 + r
```

Теперь нам нужно найти формулу, которая может дать нам сумму *этой* формулы для первых 10 000 натуральных чисел (1, 2, 3, ...). Символ сигма `Σ` обозначает суммирование. Добавим его к нашей формуле:

```math
Σxn^2 + r
```

... и переопределим `n` как ряд натуральных чисел от 1 до 10 000 включительно. Это равенство пока не слишком полезно. Интуитивно оно выглядит правильно, но, если задать `n=10,000` и `r=5,242,880`, как нам нужно, оно просто [выдает результат](https://www.wolframalpha.com/input?i=%CE%A3n%5E2+%2B+r+where+n+%3D+1+to+10%2C000+and+r+%3D+5%2C242%2C880): `385,812,135,000` (385 ГБ). Результат не только намного ниже нашего ограничения размера файла в 5 ТиБ — нет ни одного способа изменить формулу, чтобы получить этот результат.

Попробуем ввести регулятор для настройки:





```math
Σxn^2 + r
```

... где `x` — скалярное значение, которое можно вычислить, чтобы получить 5 ТиБ в качестве результата. Теперь можно приравнять равенство к нашему ограничению размера файла и вычислить `x`:

```math
Σxn^2 + r = 5,497,558,138,880
```

Часто суммирование выполняется итеративно, как в цикле `for` или `while`. Но оказывается, у нас есть прекрасная формула: [известный способ](https://www.math-only-math.com/sum-of-the-squares-of-first-n-natural-numbers.html) легко вычислить сумму квадратов первых `n` натуральных чисел:

```math
Σn^2 = n(n+1)(2n+1)/6
```





Преобразование в полином упрощает вид:





```math
Σn^2 = (2n^3 + 3n^2 + n)/6
```

Переменные `x` и `r` можно добавить к обеим сторонам:

```math
Σxn^2 + r = x(2n^3 + 3n^2 + n)/6 + rn
```





Наконец, приравниваем нашу новую формулу к 5 ТиБ:





```math
x(2n^3 + 3n^2 + n)/6 + rn = 5,497,558,138,880
```

Теперь нам нужно решить ее для `x`, установив `n=10,000` (общее количество фрагментов). Это даст возможность вычислить статический скаляр для заданной скорости передачи данных. Вместо того, чтобы решать вручную, [подставим это в Wolfram Alpha](https://www.wolframalpha.com/input?i=x%282n%5E3+%2B+3n%5E2+%2B+n%29%2F6+%2B+r+*+n+%3D+5%2C497%2C558%2C138%2C880+solve+for+x+where+n+%3D+10%2C000):

```math
x = -(2 (125 r - 68719476736)) / 8334583375
```

Это уже кое-что! Если бы скорость передачи данных была равна минимальному размеру фрагмента (5 МиБ), [мы бы получили](https://www.wolframalpha.com/input?i=x%282n%5E3+%2B+3n%5E2+%2B+n%29%2F6+%2B+r+*+n+%3D+5%2C497%2C558%2C138%2C880+solve+for+x+where+n+%3D+10%2C000+and+r+%3D+5%2C242%2C880) статическое скалярное значение:

```math
136,128,233,472 / 8,334,583,375
```

В компьютерном мире это представляет значение float64, равное `16.33293799427617`. Наша формула для определения размера фрагмента ти в этом случае будет такой:

```math
s = 16.33293799427617n^2 + 5,242,880
```

Где `s` — размер фрагмента.

Но остается еще одна проблема. В реальном мире не может быть полезной нагрузки с нецелыми байтами. Нам нужно округлить каждое значение. Мы будем использовать Python и округлим вниз:





**`Python`**

```python title="Python"
math.floor(16.33293799427617 * pow(part_number, 2)) + 5_242_880
```





Мы пришли к конкретному примеру исходной функции, приведенной в этом руководстве.





## Создание базового средства добавления





Рассмотрим простой псевдокод в стиле Python для добавления файла, отображаемого в реальном времени, используя все, что мы изучили в этом руководстве:





**`Python`**

```python title="Python"
import math
from datetime import datetime, timezone
from typing import Callable

# The minimum size, in bytes, for a single, non-final part upload.
MINIMUM_PART_SIZE = 5_242_880
# The maximum filesize in
MAXIMUM_PART_COUNT = 10_000
# The maximum size, in bytes, for an AWS upload.
MAXIMUM_FILE_SIZE = 5_497_558_138_880

# The data rate at which every part is an equal size, and could not
# be any uniformly larger without violating the maximum total file
# size if 10_000 parts were to be uploaded. it works out to
# ~549.8 MB per payload. By enforcing this we actually never need
# to check if a part exceeds the maximum allowed part size, as our
# parts will never exceed ~549.8 MB.
MAXIMUM_DATA_RATE = MAXIMUM_FILE_SIZE // MAXIMUM_PART_COUNT

def create_part_size_calculator(format_bytes_per_second: int) -> Callable[[int], int]:
    """
    Returns a function that takes in a `part_number` and returns a
    `part_size` based on `data_rate`.
    """
    ...

def upload_render(data_stream: DataStream, channel: int = 0) -> None:
    """
    Uploads an asset for data_stream, which is a custom IO class that pulls remaining
    upload data from an internal buffer or file, depending on how well the upload is
    keeping pace with the render.

    Uploads to `channel`
    """

    asset = c2c.asset_create(
        extension=data_stream.extension, 
        filetype=data_stream.mimetpye, 
        channel=channel,
        offset=datetime.now(timezone.utc) - data_stream.created_at()
    )

    calculate_part_size = create_part_size_calculator(data_stream.data_rate())
    next_part_number = 0

    while True:
        next_payload_size = calculate_part_size(next_part_number)

        # Waits until one or more chunks worth of data is ready for upload. Cache 
        # whether our data stream has completed writing the file, and the current 
        # number of bytes we have remaining to upload at this time.
        available_bytes, stream_complete = data_stream.wait_for_available_data(
            minimum_bytes=next_payload_size
        )

        # Build the list of parts to request based on our available data.
        parts = []
        while available_bytes > 0:
            payload_size = calculate_part_size(next_part_number)

            if available_bytes < payload_size and not stream_complete:
                break

            payload_size = min(payload_size, available_bytes)

            parts.append(
                c2c.RealtimeUploadPart(
                    part_number=next_part_number,
                    part_size=payload_size,
                    is_final=False
                )
            )

            available_bytes -= payload_size
            next_part_number += 1

        # If our stream is done writing, mark the last part as final.
        if stream_complete:
            parts[-1].is_final = True

        # Create the part URLs using the C2C endpoint.
        response = c2c.create_realtime_parts(
            asset_id=asset.id,
            asset_name=None if not stream_complete else data_stream.filename,
            asset_filesize=None if not stream_complete else data_stream.size(),
            parts=parts
        )

        # Upload each part to its URL.
        for part, part_url in zip(parts, response.upload_urls):
            part_data = data_stream.read(bytes=part.size)
            c2c.upload_chunk(part_data, part_url, data_stream.mimetype)

        if stream_complete:
            break

```




<Warning title="Расширенное добавление">
  Приведенный выше код демонстрирует только базовый процесс добавления файла в реальном времени. На самом деле эту логику нужно будет дополнить [обработкой ошибок](/camera-to-cloud/how-to-handle-errors) и способами [расширенного добавления](/camera-to-cloud/how-to-advanced-uploads).
</Warning>


## Далее

Добавления в реальном времени позволяют максимально сократить отклик вашей интеграции — ресурсы можно воспроизвести в Frame.io через несколько секунд после завершения записи. В [другом руководстве](/camera-to-cloud/how-to-advanced-uploads) рассматриваются способы расширенного добавления и требования к нему. Хотя оно написано для базовых добавлений, основная часть руководства применима и к добавлениям в реальном времени.

Если вы еще этого не сделали, рекомендуем связаться с нашей командой, а затем перейти к следующему руководству. Надеемся на скорую обратную связь!