Glossário

O fluxo de upload de mídia INIT APPEND FINALIZE da API do X, passo a passo

Taras Shynkarenko
Taras Shynkarenko
•Atualizado: •9 min de leitura
O fluxo de upload de mídia INIT APPEND FINALIZE da API do X em três endpointsO fluxo de upload de mídia INIT APPEND FINALIZE da API do X em três endpoints

TL;DR, Resposta Rápida

9 min de leitura

Upload de vídeo em partes no X v2 são quatro chamadas: POST /2/media/upload/initialize devolve um media id, POST /2/media/upload/{id}/append recebe cada parte com um segment_index, POST /2/media/upload/{id}/finalize fecha a sessão, e GET /2/media/upload?command=STATUS consulta o processing_info até o state ser succeeded ou failed. Os antigos parâmetros command=INIT e command=APPEND sumiram de tudo menos desse GET de status. O segment_index para em 999 e o X recomenda partes de 5 MB, o que não chega perto dos 16 GB de total_bytes que o schema de inicialização aceita.

O que é o fluxo de upload de mídia INIT APPEND FINALIZE da API do X?

São quatro chamadas no fluxo de upload de mídia INIT APPEND FINALIZE da API do X: três POSTs que movem o arquivo e um GET que relata o que o X fez com ele depois. O X lista as quatro nessa ordem no guia de upload em partes.

  1. INIT, POST /2/media/upload/initialize, que o X descreve como "start the session and get a media_id"
  2. APPEND, POST /2/media/upload/{id}/append, "upload each chunk"
  3. FINALIZE, POST /2/media/upload/{id}/finalize, "complete the upload"
  4. STATUS, GET /2/media/upload, "wait for processing when processing_info is returned"

Os nomes dos comandos sobreviveram à mudança para a v2, o transporte não. O X põe o aviso logo abaixo da lista: "Do not send command=INIT, command=APPEND, or command=FINALIZE to POST /2/media/upload. Those command-style parameters were the previous upload protocol. The v2 flow uses the dedicated paths above. command=STATUS is still used only on the status GET."

Ou seja, um dos quatro comandos ainda existe como parâmetro de query e três não. Código escrito para a v1.1 quebra nos três POSTs e continua funcionando na consulta, o que é um jeito confuso de falhar.

As quatro chamadas ficam atrás do mesmo escopo OAuth 2.0, media.write, inclusive o GET de status. Ler o estado de processamento do seu próprio upload exige um escopo de escrita, e o X não publica alternativa somente leitura.

O que cada etapa envia e devolve?

Cada etapa leva parâmetros diferentes, e só duas das quatro devolvem algo que você guarda.

EtapaEndpointVocê enviaVocê recebe
INITPOST /2/media/upload/initializemedia_type, total_bytes, media_category, opcionalmente additional_owners e sharedid, media_key, expires_after_secs
APPENDPOST /2/media/upload/{id}/appendmedia e segment_indexexpires_at
FINALIZEPOST /2/media/upload/{id}/finalizenada além do id no caminhoid, media_key, size, expires_after_secs, processing_info
STATUSGET /2/media/upload?command=STATUS&media_id=media_id, opcionalmente commandid, media_key, size, processing_info, video ou image

O INIT recebe um corpo JSON, não campos de formulário, e o X diz isso no guia: "Send a JSON body, not multipart form fields." O enum de media_type vai de video/mp4 e video/quicktime a text/srt e text/vtt, passando por dois formatos 3D que quase ninguém nota, model/gltf-binary e model/vnd.usdz+zip. O campo total_bytes tem um teto rígido de schema em 17179869184, que são 16 GiB.

{
  "data": {
    "id": "1880028106020515840",
    "media_key": "13_1880028106020515840",
    "expires_after_secs": 86400
  }
}

Esse expires_after_secs de 86400 no exemplo do próprio X é o relógio da sessão: um dia entre o INIT e anexar a mídia pronta a alguma coisa. O id segue o padrão ^[0-9]{1,19}$, e o media_key põe na frente dele um número de tipo e um sublinhado, o mesmo formato 13_ que a Ads API documenta quando chama o valor de id de vídeo.

O APPEND é a única etapa cuja resposta não diz nada de útil sobre a mídia. O schema dele tem um campo só, expires_at, descrito como "Epoch seconds when the upload session expires." Todas as outras etapas informam a vida restante da sessão como expires_after_secs, uma contagem relativa. O APPEND informa como timestamp absoluto. O mesmo fato, duas unidades, três grafias de campo em quatro endpoints.

O FINALIZE é a requisição mais vazia do fluxo. Ele recebe o id no caminho e mais nada, sem corpo e sem parâmetros de query, e é por isso que o curl inteiro cabe em duas linhas:

curl -X POST "https://api.x.com/2/media/upload/1880028106020515840/finalize" \
  -H "Authorization: Bearer $USER_ACCESS_TOKEN"

A resposta dele é onde a bifurcação de verdade acontece. O X põe a regra em uma frase: "If processing_info is returned, proceed to Step 4 to wait for processing. If not, the media is ready to use." Uma imagem costuma pular a etapa quatro. Um vídeo nunca pula.

Uma pessoa grava vídeo com o celular, o tipo de arquivo que é dividido em partes para o upload.

Como funciona o segment_index?

segment_index é um contador simples que é seu, começa em zero, e o schema fixa as duas pontas: "minimum: 0, maximum: 999."

A orientação do X sobre tamanho de parte fica no guia e não no schema: "Keep each segment at or below 5 MB (the server maximum is 8 MB). Segments are indexed from 0." O exemplo em Python no mesmo guia lê o arquivo em blocos de 4 MB e incrementa o índice depois de cada chamada bem-sucedida.

curl -X POST "https://api.x.com/2/media/upload/1880028106020515840/append" \
  -H "Authorization: Bearer $USER_ACCESS_TOKEN" \
  -F "segment_index=0" \
  -F "media=@/path/to/chunk0.mp4"

O corpo pode ser multipart form data, como acima, ou JSON, porque o schema da requisição está registrado para os dois content types. Em JSON o campo media recebe base64. Em multipart ele recebe bytes crus.

Agora multiplique os dois tetos publicados. Mil segmentos no máximo de 8 MB do servidor dão 8 GB. Mil segmentos nos 5 MB recomendados dão 5 GB. Só que POST /2/media/upload/initialize aceita total_bytes de até 16 GiB, e o X afirma sem rodeios que uma conta X Premium ou verificada pode subir um vídeo de 16 GB em um Post. Esses dois fatos não podem ser satisfeitos ao mesmo tempo pelo APPEND como está documentado, e o X não publica segmento maior, nem caminho alternativo, nem nota dizendo que o teto de 999 muda para arquivos grandes. Qualquer coisa acima de 8 GB não tem rota documentada para entrar no fluxo.

AdaptlyPost
AdaptlyPost

Comece seu teste grátis de 7 dias

Análises multiplataforma

Caixa Social

Assistente com IA

O upload também não precisa ser sequencial em nenhum sentido publicado. O X lista "Failed chunks can be retried individually" e "Uploads can be paused and resumed" entre as vantagens do upload em partes, mas nunca diz se um segmento reenviado sobrescreve o anterior, se os índices podem chegar fora de ordem ou o que acontece se você pular um número. A mesma dúvida aparece em outras redes: a sessão de upload retomável do Instagram tem um cabeçalho de offset que todos os exemplos publicados deixam em zero, e o LinkedIn responde entregando uma lista de URLs de upload, uma por parte.

Uma tela de carregamento em um notebook, parecida com o progresso que um servidor informa ao processar um arquivo.

A matemática dos segmentos contra o teto de 16 GB
1.000 segmentos de 5 MB (recomendado)5 GB
1.000 segmentos de 8 MB (máximo do servidor)8 GB
Teto do esquema total_bytes16 GB
Mesmo no máximo do servidor de 8 MB, 1.000 segmentos chegam a apenas 8 GB, metade do que o esquema de initialize permite.

O que o comando STATUS devolve?

O STATUS devolve um objeto processing_info com três campos, e aquele em que você age é o state.

CampoO que o schema diz
state"Processing state (pending, in_progress, failed, succeeded)"
check_after_secs"Seconds to wait before polling status again"
progress_percent"Processing completion percentage"

O guia imprime o caminho feliz como um diagrama de setas: "pending to in_progress to succeeded or failed." Dois desses quatro são terminais. O exemplo de consulta do próprio X quebra o laço em succeeded e em failed e dorme por check_after_secs em qualquer outro caso, que é o formato certo, porque quem define o intervalo é o servidor e não a sua política de backoff. O exemplo do FINALIZE devolve "check_after_secs": 1, então a primeira consulta vem rápido.

curl "https://api.x.com/2/media/upload?command=STATUS&media_id=1880028106020515840" \
  -H "Authorization: Bearer $USER_ACCESS_TOKEN"

Vale conhecer duas lacunas antes de montar o laço.

Os quatro valores de estado vivem em uma string de descrição, não em um enum. O schema tipa state como string simples, sem lista de valores permitidos, então os quatro nomes que o X imprime são documentação e não um conjunto fechado. Trate um estado desconhecido como "continue consultando" em vez de como erro.

A lacuna maior é que processing_info não tem onde pôr um motivo de falha. O schema dele declara exatamente três propriedades e depois additionalProperties: false, então uma resposta que diz "state": "failed" não traz código, nem mensagem, nem subcódigo junto. O protocolo v1.1 devolvia um objeto de erro dentro de processing_info, com nome e mensagem. O schema v2 como publicado não tem campo para isso, o que deixa "failed" como o diagnóstico inteiro.

progress_percent está documentado em todos os schemas de processing_info da referência de mídia e não aparece em nenhuma resposta de exemplo do X, então conte com ele ausente em vez de zerado.

Por que um upload concluído ainda falha em POST /2/tweets?

Porque o X confere o arquivo duas vezes contra duas pessoas diferentes, e diz isso duas vezes. A introdução de mídia abre com o tema: "Upload and posting are separately enforced. A file that uploads successfully can still be rejected when you attach it to a Post."

A primeira conferência roda contra o usuário que fez o upload, no INIT e no FINALIZE. A segunda roda contra o usuário que publica, quando o media_id chega em POST /2/tweets. O X nomeia a falha exatamente:

{
  "title": "Forbidden",
  "detail": "This user is not allowed to post a video longer than 20 minutes.",
  "type": "about:blank",
  "status": 403
}

Vinte minutos é a cifra padrão nessa string. O X observa que o número muda: "N is the posting user's duration cap (20 minutes by default, 125 minutes for Premium / verified)." Ou seja, o mesmo media_id, finalizado uma vez e processado até succeeded, anexa em uma conta e devolve 403 em outra. O direito segue a conta, e as faixas que decidem qual duração de vídeo uma conta recebe são as mesmas faixas do X Premium, não o seu plano de desenvolvedor.

Os limites de composição do Post valem no mesmo instante. O X permite "up to 4 photos, 1 animated GIF, or 1 video" em um Post, e um media_id que viola essa mistura falha no anexo mesmo com o upload tendo saído limpo. A sequência prática para qualquer coisa longa é o passo a passo completo para colocar vídeo de alta qualidade no X, com o 403 tratado como resultado normal e não como exceção.

Perguntas frequentes

Quais endpoints substituem command=INIT e command=APPEND na API do X v2?

POST /2/media/upload/initialize e POST /2/media/upload/{id}/append. O X afirma que os parâmetros em formato de comando "were the previous upload protocol" e não devem mais ser enviados para POST /2/media/upload.

O command=STATUS ainda vale na API do X v2?

Sim, e é o único que vale. O X escreve que "command=STATUS is still used only on the status GET", ou seja, GET /2/media/upload?command=STATUS&media_id=. O schema marca o parâmetro command como opcional mesmo que todos os exemplos publicados o enviem.

Qual o segment_index máximo no endpoint append da API do X?

  1. O schema da requisição de append define segment_index com mínimo 0 e máximo 999, o que limita um arquivo a 1000 partes.

Qual o tamanho máximo de cada parte do APPEND?

O X recomenda 5 MB e aponta 8 MB como máximo do servidor. O exemplo em Python da própria empresa lê o arquivo em blocos de 4 MB.

AdaptlyPost
AdaptlyPost

Comece seu teste grátis de 7 dias

Análises multiplataforma

Caixa Social

Assistente com IA

Quais são os estados de processamento de upload de mídia do X?

pending, in_progress, succeeded e failed. O X imprime a progressão como pending para in_progress para succeeded ou failed, ainda que o schema tipe state como string aberta e não como enum.

Por que um media_id finalizado com sucesso falha em POST /2/tweets?

Upload e publicação são fiscalizados separadamente contra direitos diferentes. Se o usuário que publica não pode anexar um vídeo tão longo, a requisição do Post devolve 403 Forbidden com o detalhe "This user is not allowed to post a video longer than N minutes."

Por quanto tempo uma sessão de upload de mídia do X fica válida antes de expirar?

O próprio exemplo de INIT do X devolve um expires_after_secs de 86400, ou seja, um dia entre o INIT e anexar a mídia pronta a alguma coisa. O FINALIZE informa o tempo restante do mesmo jeito, como expires_after_secs. O APPEND foge desse padrão e devolve expires_at, um timestamp epoch absoluto em vez de uma contagem regressiva, então o mesmo relógio de sessão aparece em duas unidades diferentes.

Fazer upload de uma foto no X exige consultar o endpoint STATUS?

Quase nunca. A regra do X é que, se o FINALIZE não devolve bloco processing_info nenhum, a mídia está pronta para uso, e um upload de imagem costuma voltar sem esse bloco. Um vídeo nunca volta sem ele, então o passo quatro é, na prática, coisa de vídeo.

O endpoint STATUS usa um escopo OAuth diferente das etapas de upload?

As quatro chamadas, INIT, APPEND, FINALIZE e STATUS, ficam atrás do mesmo escopo media.write. Consultar o estado de processamento do próprio upload exige um escopo de escrita, e o X não publica nenhuma alternativa somente leitura.

Quais tipos de mídia podem ser enviados pelo endpoint initialize da API do X?

O enum media_type do INIT vai de video/mp4 e video/quicktime até text/srt e text/vtt, chegando a dois formatos 3D, model/gltf-binary e model/vnd.usdz+zip. Um único endpoint de upload cobre vídeo, legendas e arquivos 3D.

Este artigo foi útil para você?

Conte-nos o que você achou!

Veja-nos mais no Google

Um clique marca a AdaptlyPost como fonte preferida e nossos artigos passam a aparecer mais acima nas suas Principais notícias, no modo IA e nas visões gerais com IA.

Antes de ir...

AdaptlyPost

AdaptlyPost

Agende seu conteúdo em todas as plataformas

Gerencie todas as suas contas de redes sociais em um só lugar com o AdaptlyPost.

Análises multiplataforma

Caixa Social

Assistente com IA

Termos relacionados do glossário

Artigos Relacionados