> This page is for Camera to Cloud.

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

# Instruções: Como fazer o upload (em tempo real)

## Introdução





Com base em nosso conhecimento básico de upload, vamos explorar o upload de ativos em tempo real conforme são criados. Essa abordagem possibilita fazer upload de arquivos durante gravação, renderização ou streaming antes de conhecer o tamanho final.





A API de uploads em tempo real permite que os ativos se tornem reproduzíveis no Frame.io apenas alguns segundos após a conclusão da gravação, aprimorando significativamente a eficiência do fluxo de trabalho.





## Vídeo de demonstração

Para uma visualização rápida desta funcionalidade, assista ao nosso [vídeo de demonstração](https://f.io/qjwfGmTa). A demonstração mostra uma renderização sendo carregada do Adobe Media Encoder em tempo real, com o vídeo reproduzível no Frame.io apenas 5 segundos após a conclusão da renderização.

## Pré-requisitos

Caso ainda não tenha feito isso, consulte o guia [Implementação do C2C: Configuração](./implementing-c2c-setting-up). Você precisará do `access_token` obtido durante o [processo de autenticação e autorização](./implementing-c2c-authentication-and-authorization). Usaremos o mesmo [ativo de teste](https://f.io/Rq1q5CzB) do guia de upload básico para nossos exemplos. Recomenda-se familiaridade com o [guia de Uploads básicos](./how-to-basic-upload), pois desenvolveremos esses conceitos.

## Criar um ativo em tempo real

Os uploads em tempo real começam com um processo modificado de criação de ativos. Ao criar o ativo, defina `is_realtime_upload` como `true` e omita o parâmetro `filesize` (ou defina como `null`), pois o tamanho final não é conhecido durante a criação:

```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="Especificação do ponto de acesso da API">
  A documentação para `/v2/devices/assets` pode ser [encontrada aqui](/camera-to-cloud/api-reference/device-asset-create).
</Info>

<Warning title="Extensão e nome do arquivo">
  Ativos em tempo real requerem uma extensão de arquivo. Se o nome do arquivo não for conhecido ao criar o ativo, você pode usar o campo `extension` (formato: `'.mp4'`). Essa abordagem é preferível quando você planeja atualizar o nome do ativo posteriormente.
</Warning>


A resposta para ativos em tempo real é simplificada em comparação à criação de ativos padrão:





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

Observe que `upload_urls` está ausente. Para uploads em tempo real, geraremos URLs de upload por demanda conforme o arquivo é criado.

## Solicitar URLs de upload

Vamos solicitar um URL para a primeira metade do nosso arquivo (10.568.125 bytes), usando o `asset_id` da resposta anterior:

```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="Especificação do ponto de acesso da API">
  A documentação para `/v2/devices/assets/{asset_id}/realtime_upload/parts` pode ser [encontrada aqui](/camera-to-cloud/api-reference/device-create-realtime-upload-parts).
</Info>


Entender os parâmetros da solicitação:




* `parts`: uma lista de partes de upload para as quais precisamos de URLs. Solicitar vários URLs em uma única chamada melhora a eficiência.

* `number`: o número sequencial da parte, começando em 1. Os números podem ser pulados e as partes enviadas em qualquer ordem, mas serão montadas sequencialmente. Não pode exceder 10.000 (limite da AWS). * `size`: tamanho da parte em bytes. Deve estar em conformidade com as [restrições de upload multiparte da AWS](https://docs.aws.amazon.com/AmazonS3/latest/userguide/qfacts.html). * `is_final`: indica se esta é a parte final do arquivo.

A resposta contém as URLs de upload solicitados:





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

A lista `upload_urls` corresponde diretamente à ordem da solicitação `parts`.

Agora faça upload do primeiro bloco como no guia de uploads básicos:





```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 @-
```





Em seguida, solicite um URL para a segunda e última parte:





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





Observe estas adições importantes:




* `is_final` é definido como `true` para a última parte, sinalizando que o upload será concluído após este bloco
* `asset_filesize` fornece o tamanho total do arquivo, que é necessário quando qualquer parte tem `is_final: true`




Após receber o URL na resposta:





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





Faça upload do bloco final:





```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="Manuseio da parte final">
  


Quando a parte final é enviada, o Frame.io inicia a montagem do arquivo completo. Este processo inclui um período de tolerância de 60 segundos para que as partes restantes sejam concluídas. Recomendamos fazer upload da parte final somente depois que todas as outras partes foram enviadas com sucesso.



</Warning>


Pronto! Navegue para Frame.io para ver seu ativo em tempo real carregado com sucesso. 🎉





## Gerenciar nomes de ativos

Se o nome do arquivo não for conhecido durante a criação do ativo, você pode usar o campo `extension` sem um `name`:

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





O sistema atribuirá um nome padrão:





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

Você pode atualizar este nome incluindo um campo `asset_name` ao solicitar URLs de upload:

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





O nome só será atualizado se o ativo ainda tiver seu nome padrão. Se foi renomeado na interface do Frame.io ou atualizado anteriormente, a solicitação será ignorada.





## Otimizar solicitações de URL





Para maior eficiência, solicite URLs para quantas partes você tiver dados disponíveis no momento, em vez de individualmente. Esta abordagem é particularmente valiosa para arquivos grandes onde a velocidade de upload pode ficar atrás da geração de dados.





## Processar cabeçalhos de arquivos de mídia





Alguns formatos de mídia exigem cabeçalhos no início do arquivo que não são escritos até que todo o arquivo seja concluído. Isso gera um desafio quando o cabeçalho é menor que o tamanho mínimo de parte da AWS de 5 MiB (5.242.880 bytes).





Nossa recomendação:




1. Reserve os primeiros 5.242.880 bytes de dados de mídia sem fazer upload
2. Comece fazendo upload de partes iniciando com `part_number=2`
3. Quando o arquivo estiver completo, adicione o cabeçalho aos dados reservados
4. Solicite um URL para `part_number=1` e faça upload deste bloco combinado





Esta abordagem garante que seu primeiro bloco atenda ao requisito de tamanho mínimo preservando a estrutura adequada do arquivo.





## Dimensionar tamanho da parte para desempenho ideal





A AWS impõe limites que afetam a estratégia de upload:



* Tamanho máximo de arquivo: 5 TiB (5.497.558.138.880 bytes)
* Número máximo de partes: 10.000
* Tamanho mínimo da parte: 5 MiB (5.242.880 bytes)




Um tamanho fixo de peça implica em compromissos:



* Usar o tamanho mínimo (5 MiB) para todas as 10.000 partes limita o tamanho total do arquivo para aproximadamente 52,4 GB
* Distribuir uniformemente o tamanho máximo do arquivo exigiria blocos de aproximadamente 550 MB, muito grandes para streaming eficiente de arquivos menores




Precisamos de uma fórmula que equilibre essas restrições, começando com partes pequenas para uploads responsivos, garantindo que seja possível lidar com arquivos muito grandes, se necessário.





### Fórmula de tamanho de parte recomendado





Esta é nossa abordagem sugerida em 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

```

... onde `part_number` está entre `1` e `10_000`, inclusive, e `format_bytes_per_second` é o número médio esperado de bytes que o arquivo deve consumir por segundo. Explicaremos como a fórmula foi criada [mais adiante](/camera-to-cloud/how-to-upload-realtime#showing-our-work).
<Info title="Valor escalar">
  A variável `scalar` e o cálculo podem ser um pouco confusos à primeira vista, mas é uma ferramenta matemática que garante que, independentemente do valor usado para `format_bytes_per_second`, se alimentarmos todos os valores `part_number` permitidos de `1` a `10_0000` na função, receberemos um conjunto de valores que totaliza *exatamente* nosso limite de tamanho de arquivo de 5 TiB — bem, o mais exato possível. Mostramos [nosso trabalho](/camera-to-cloud/how-to-upload-realtime#showing-our-work) mais adiante sobre como chegamos a essa fórmula.
</Info>

<Info title="Arredondamento por número inteiro">
  


Ao usar arredondamento por número inteiro, deixamos alguns bytes de lado, mas garantimos que o arredondamento regular em 10.000 partes não exceda acidentalmente nosso tamanho máximo de arquivo permitido. No máximo, 10.000 bytes ou 10 KB serão deixados de lado dessa forma, uma compensação aceitável.



</Info>


As características importantes dessa fórmula são:




* Ao fazer upload de 10.000 partes, a quantidade total de dados carregados ficará dentro de 10 KB do nosso limite de tamanho de arquivo de 5 TiB.
* Otimiza conteúdos menores e mais eficientes no início para aumentar a capacidade de resposta para clipes curtos e de duração média.
* Clipes muito longos terão capacidade de resposta reduzida entre o final da gravação de um arquivo e ele se tornar reproduzível no Frame.




A compensação entre o segundo e o terceiro ponto é reduzida pelo fato de que a maioria dos clipes não atingirá o tamanho em que o terceiro ponto entra em ação. Estamos trocando capacidade de resposta aumentada da *MAIORIA* dos arquivos por capacidade de resposta reduzida de muito poucos.

Uma versão mais avançada e eficiente da nossa fórmula (que gera uma função anônima `part_size_calculator` com nosso escalar estático e taxa de dados pré-computados e incorporados) pode ser assim:

**`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

```





### Como a fórmula funciona.





Vamos analisar as características de saída da fórmula acima em vários tipos de arquivo comuns.

**Exemplo 1**: Formato da web

Para formatos reproduzíveis na web com taxa de aproximadamente 5,3 MB/s ou menos (a maioria dos arquivos H.264/H.265/HEVC), obteremos uma progressão de tamanho de conteúdo semelhante a:




| Total de partes | Bytes de conteúdo | MB de conteúdo | Total de bytes do arquivo | Total de GB do arquivo |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 5,242,896 | 5,2 MB | 5,242,896 | 0,0 GB |
| 1,000 | 21,575,817 | 21,6 MB | 10,695,361,357 | 10,7 GB |
| 5,000 | 413,566,329 | 413,6 MB | 706,957,655,928 | 707,0 GB |
| 10,000 | 1,638,536,679 | 1.638,5 MB | 5,497,558,133,921 | 5.497,6 GB |
**Chave das colunas da tabela** – `Total Parts`: o número total de partes de arquivo enviadas para a AWS. - `Payload Bytes`: o tamanho do conteúdo da chamada PUT da AWS quando `part_number` é igual a `Total Parts`. - `Payload MB`: Como `Payload Bytes`, mas em megabytes. - `Total File Bytes`: o número total de bytes enviados para o arquivo quando as partes sequenciais `Total Parts` foram enviadas. - `Total File GB`: Como `Total File Bytes`, mas em GB.

Esses valores são bem equilibrados para uploads em tempo real, especialmente de codecs de reprodução na web como H.264. A maioria ficará abaixo de 10,7 GB e, portanto, será concluída em até 1.000 partes. O tamanho do conteúdo nunca excederia 21,6 MB.





Mesmo que dividíssemos nossas partes ao meio, o tamanho do conteúdo ainda assim nunca ultrapassaria 413,5 MB. O upload totalizaria 707 GB, mais do que suficiente para a maioria dos arquivos da web.





É apenas quando nos aproximamos do final da contagem de partes permitidas que o tamanho do arquivo começa a aumentar drasticamente. No entanto, nunca excede 1,7 GB, bem abaixo do limite da AWS de 5 GiB por parte.

**Exemplo 2**: Prores 422 LT Prores 422 LT [tem uma taxa de dados de 102 Mbps](https://www.wolframalpha.com/input?i=-%282+%28-68%2C719%2C476%2C736+%2B+125+12%2C750%2C000%29%29%2F8%2C334%2C583%2C375) e gera uma tabela como esta:
| Total de partes | Bytes de conteúdo | MB de conteúdo | Total de bytes do arquivo | Total de GB do arquivo |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 12,750,016 | 12,8 MB | 12,750,016 | 0,0 GB |
| 1,000 | 28,857,758 | 28,9 MB | 18,127,308,783 | 18,1 GB |
| 5,000 | 415,443,954 | 415,4 MB | 735,107,948,432 | 735,1 GB |
| 10,000 | 1,623,525,817 | 1.623,5 MB | 5,497,558,133,958 | 5.497,6 GB |




Esta tabela revela propriedades úteis comparadas à nossa fórmula otimizada para web. Nas primeiras 1.000 partes, conseguimos fazer upload de 8 GB a mais de arquivo. Conteúdos iniciais maiores significam que não precisaremos solicitar URLs muito rapidamente no início, tornando o upload mais eficiente para a taxa de dados mais alta. O tamanho do nosso conteúdo no final do processo de upload continua sendo grande.

**Exemplo 2**: Camera raw

Finalmente, vamos testar um formato Camera RAW que tem uma taxa de dados de 280 MB/s. Com dados chegando tão rapidamente, tentar fazer upload em blocos de 5 MiB no início simplesmente não faz sentido:




| Total de partes | Bytes de conteúdo | MB de conteúdo | Total de bytes do arquivo | Total de GB do arquivo |
| ----------: | ------------: | ---------: | ----------------: | -------------: |
| 1 | 280,000,008 | 280,0 MB | 280,000,008 | 0,3 GB |
| 1,000 | 288,091,460 | 288,1 MB | 282,701,200,139 | 282,7 GB |
| 5,000 | 482,286,516 | 482,3 MB | 1,737,245,341,542 | 1.737,2 GB |
| 10,000 | 1,089,146,065 | 1.089,1 MB | 5,497,558,133,870 | 5.497,6 GB |




Além do conteúdo inicial ser mais eficiente, estamos economizando mais de meio gigabyte na extremidade superior, o que tornará essas chamadas de rede menos suscetíveis a eventos adversos na rede.





### Mostrando nosso trabalho





Antes de reunir tudo em um exemplo de carregador, vamos ver como chegamos à nossa fórmula.





O que precisávamos fazer era criar uma fórmula que trocasse conteúdos úteis grandes e pesados no final do nosso limite de partes, que a maioria dos uploads nunca alcançará, por conteúdos úteis leves e eficientes no início, onde todos os uploads podem se beneficiar. Ao mesmo tempo, queríamos garantir que nosso algoritmo chegue perto do limite de tamanho de arquivo de 5 TiB *exatamente no* número da parte 10.000.





Era hora de usar um pouco de cálculo.





Queremos que nosso gráfico cresça exponencialmente, então nossa fórmula provavelmente deve ser algo como:





```math
n^2
```

... onde `n` é o número da parte. Também queremos garantir que cada parte seja, no mínimo, a taxa de dados para nossa fórmula, que chamaremos de `r`:

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

Agora precisamos encontrar uma fórmula que possa nos dizer a soma *desta* fórmula para os primeiros 10.000 números naturais (1, 2, 3, ...). O símbolo sigma `Σ` denota somatória. Vamos adicioná-lo à nossa fórmula:

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

... e redefinir `n` como a série de números naturais entre 1 e 10.000, inclusive. A equação ainda não é muito útil para nós. Ela tem a forma intuitiva correta, mas se definirmos `n=10,000` e `r=5,242,880` como queremos, ela apenas [gera um resultado](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 GB). Não apenas o resultado está muito abaixo do nosso limite de tamanho de arquivo de 5 TiB, não há como manipular a fórmula para gerar esse resultado.

Vamos nos dar um controle para ajustar:





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

... onde `x` é um escalar que podemos resolver para obter 5 TiB como resultado. Agora podemos definir a equação igual ao nosso limite de tamanho de arquivo e resolver para `x`:

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

Frequentemente, as somatórias devem ser resolvidas iterativamente, como em um loop `for` ou `while`. Mas acontece que existe uma fórmula perfeita para nós: [uma forma conhecida](https://www.math-only-math.com/sum-of-the-squares-of-first-n-natural-numbers.html) de calcular facilmente a soma do quadrado para os primeiros `n` números naturais:

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





Reorganizá-la em um polinômio facilita a visualização:





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

Podemos adicionar nossas variáveis, `x` e `r`, a ambos os lados:

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





E finalmente definimos nossa nova fórmula igual a 5 TiB:





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

Agora tudo o que precisamos fazer é resolver para `x` definindo `n=10.000`, nossa contagem total de partes. Isso nos dará uma forma de calcular um escalar estático para uma determinada taxa de dados. Em vez de fazer isso manualmente, vamos [inserir no 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
```

Agora estamos chegando a algum lugar! Se nossa taxa de dados fosse o tamanho mínimo da parte (5 MiB), [obteríamos](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) um escalar estático de:

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

No mundo da computação, isso representa um valor float64 de `16.33293799427617`. Nossa fórmula para determinar o tamanho da parte nesta instância seria:

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

Onde `s` é o tamanho da nossa parte.

Ainda temos mais um problema. No mundo real, não podemos ter um conteúdo com bytes não inteiros. Precisamos arredondar cada valor. Vamos usar Python e arredondar para baixo:





**`Python`**

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





Chegamos a um exemplo concreto da função original fornecida neste guia.





## Criar um carregador básico





Vamos dar uma olhada em um pseudocódigo simples semelhante ao python para fazer upload de um arquivo sendo renderizado em tempo real, usando tudo o que aprendemos neste guia:





**`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="Upload avançado">
  O código acima demonstra apenas o fluxo básico de fazer upload de um arquivo em tempo real. Na realidade, essa lógica precisará ser aprimorada com [tratamento de erros](/camera-to-cloud/how-to-handle-errors) e técnicas de [upload avançado](/camera-to-cloud/how-to-advanced-uploads).
</Warning>


## Próximas etapas

Os uploads em tempo real oferecem uma forma de tornar sua integração o mais responsiva possível, com ativos ficando reproduzíveis no Frame.io segundos após terminarem de gravar. [Um guia posterior](/camera-to-cloud/how-to-advanced-uploads) abordará técnicas avançadas e requisitos de upload. Embora tenha sido escrito pensando em uploads básicos, a maior parte do guia ainda será aplicável aos uploads em tempo real.

Se ainda não o fez, recomendamos que entre em contato com nossa equipe e, em seguida, siga para o próximo guia. Estamos ansiosos para ter notícias suas!