Skip to Content
Referencia APIVídeosCarga avanzadaCarga multipart

Subida multiparte

Para archivos de video grandes (más de 100 MB), te recomendamos usar subidas multiparte. Este método divide tu archivo en trozos más pequeños que se suben en paralelo, lo que mejora la fiabilidad y el rendimiento con archivos grandes.

La subida multiparte se recomienda para archivos de más de 100 MB y admite archivos de hasta 60 GB.

Para una implementación más sencilla, considera usar la biblioteca Uppy, que gestiona el troceado, los reintentos y el seguimiento del progreso automáticamente.

Resumen

El proceso de subida multiparte consta de cuatro pasos:

  1. Inicializar — Crear un objeto de video y solicitar una subida multiparte
  2. Obtener URLs firmadas — Solicitar URLs pre-firmadas para cada parte (por lotes para eficiencia)
  3. Subir partes — Subir cada trozo a su URL firmada
  4. Completar — Indicar que todas las partes se han subido

Inicializar subida multiparte

Crea un objeto de video enviando una solicitud PUT a /videos/upload con useMultipart: true.

curl -X PUT https://app.ignitevideo.cloud/api/videos/upload \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "title": "Your video title", "mimeType": "video/mp4", "useMultipart": true }'

Respuesta

{ "videoId": "[VIDEO_ID]", "title": "Your video title", "multipartUpload": { "uploadId": "[UPLOAD_ID]", "key": "[S3_KEY]" } }

Guarda los valores uploadId y key; los necesitarás en todas las solicitudes posteriores.

Obtener URLs firmadas para las partes

Antes de subir las partes, necesitas obtener URLs pre-firmadas. Por eficiencia, pide las URLs en lotes en lugar de una a una.

Solicitud por lotes (recomendado)

Solicita varias URLs firmadas a la vez usando el endpoint prepare-parts.

curl -X POST "https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/[UPLOAD_ID]/prepare-parts?key=[S3_KEY]" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{"startPart": 1, "endPart": 100}'

Respuesta

{ "parts": [ { "partNumber": 1, "url": "[SIGNED_URL_FOR_PART_1]" }, { "partNumber": 2, "url": "[SIGNED_URL_FOR_PART_2]" } ] }

Solicitud de una sola parte (alternativa)

Si necesitas la URL de una parte concreta, puedes solicitarla de forma individual.

curl "https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/[UPLOAD_ID]/[PART_NUMBER]?key=[S3_KEY]" \ -H "Authorization: Bearer YOUR_TOKEN"

Subir partes

Divide tu archivo en trozos (recomendado: 5 MB - 100 MB por parte) y sube cada trozo a su URL firmada correspondiente con una solicitud PUT.

Tamaño de las partes: La subida multiparte exige un tamaño mínimo de 5 MB por parte (salvo la última). Recomendamos trozos de 10 MB para equilibrar paralelismo y sobrecarga.

El ejemplo siguiente supone que ya obtuviste todas las URLs firmadas necesarias. Para archivos con más de 100 partes tendrás que pedir las URLs por lotes. Consulta el ejemplo completo más abajo para gestionar archivos grandes.

const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB chunks const file = yourVideoFile; // File object const totalParts = Math.ceil(file.size / CHUNK_SIZE); const uploadedParts = []; // Upload parts in parallel (limit concurrency to 5) const uploadPart = async (partNumber, signedUrl) => { const start = (partNumber - 1) * CHUNK_SIZE; const end = Math.min(start + CHUNK_SIZE, file.size); const chunk = file.slice(start, end); const response = await fetch(signedUrl, { method: 'PUT', body: chunk }); // Get the ETag from the response headers const etag = response.headers.get('ETag'); return { PartNumber: partNumber, ETag: etag }; }; // Upload all parts for (let i = 0; i < totalParts; i += 5) { const batch = []; for (let j = i; j < Math.min(i + 5, totalParts); j++) { const partNumber = j + 1; const signedUrl = partsData.parts.find(p => p.partNumber === partNumber)?.url; if (signedUrl) { batch.push(uploadPart(partNumber, signedUrl)); } } const results = await Promise.all(batch); uploadedParts.push(...results); }

Importante: Debes recoger la cabecera ETag de la respuesta de cada subida de parte. Son necesarias para completar la subida multiparte.

Completar subida multiparte

Cuando todas las partes estén subidas, envía una solicitud de finalización con la lista de partes y sus ETags.

curl -X POST "https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/[UPLOAD_ID]/complete?key=[S3_KEY]" \ -H "Authorization: Bearer YOUR_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "PartNumber": 1, "ETag": "\"etag1\"" }, { "PartNumber": 2, "ETag": "\"etag2\"" } ] }'

En subidas con más de 100 partes puedes usar fetchPartsFromStorage: true en lugar de pasar el array parts. El servidor recuperará la información de las partes automáticamente.

// For large uploads with many parts const completeResponse = await fetch( `https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/${uploadId}/complete?key=${encodeURIComponent(key)}`, { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_TOKEN', 'Content-Type': 'application/json' }, body: JSON.stringify({ fetchPartsFromStorage: true }) } );

Proceso de codificación

Tras completar la subida multiparte, el video pasará a codificarse. Este proceso puede tardar según el tamaño del video y la complejidad de la codificación.

Puedes comprobar el estado de codificación de un video llamando al endpoint /videos/[VIDEO_ID] como se describe en la sección Obtener un video.

Ejemplo completo

Aquí tienes un ejemplo completo en JavaScript que implementa la subida multiparte con seguimiento del progreso:

async function uploadLargeVideo(file, title, token) { const CHUNK_SIZE = 10 * 1024 * 1024; // 10MB const BATCH_SIZE = 100; const CONCURRENT_UPLOADS = 5; // Step 1: Initialize multipart upload const initResponse = await fetch('https://app.ignitevideo.cloud/api/videos/upload', { method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ title, mimeType: file.type, useMultipart: true }) }); const { videoId, multipartUpload } = await initResponse.json(); const { uploadId, key } = multipartUpload; // Calculate total parts const totalParts = Math.ceil(file.size / CHUNK_SIZE); const uploadedParts = []; let uploadedBytes = 0; // Step 2 & 3: Get signed URLs and upload parts in batches for (let batchStart = 1; batchStart <= totalParts; batchStart += BATCH_SIZE) { const batchEnd = Math.min(batchStart + BATCH_SIZE - 1, totalParts); // Get signed URLs for this batch const urlsResponse = await fetch( `https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/${uploadId}/prepare-parts?key=${encodeURIComponent(key)}`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ startPart: batchStart, endPart: batchEnd }) } ); const { parts } = await urlsResponse.json(); // Upload parts with concurrency limit for (let i = 0; i < parts.length; i += CONCURRENT_UPLOADS) { const chunk = parts.slice(i, i + CONCURRENT_UPLOADS); const uploads = chunk.map(async ({ partNumber, url }) => { const start = (partNumber - 1) * CHUNK_SIZE; const end = Math.min(start + CHUNK_SIZE, file.size); const blob = file.slice(start, end); const response = await fetch(url, { method: 'PUT', body: blob }); uploadedBytes += blob.size; const progress = (uploadedBytes / file.size) * 100; console.log(`Upload progress: ${progress.toFixed(1)}%`); return { PartNumber: partNumber, ETag: response.headers.get('ETag') }; }); const results = await Promise.all(uploads); uploadedParts.push(...results); } } // Step 4: Complete multipart upload uploadedParts.sort((a, b) => a.PartNumber - b.PartNumber); await fetch( `https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/${uploadId}/complete?key=${encodeURIComponent(key)}`, { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ parts: uploadedParts }) } ); console.log(`Upload complete! Video ID: ${videoId}`); return videoId; }

Manejo de errores

Si falla una subida, puedes reintentar partes concretas sin reiniciar toda la subida. El uploadId sigue siendo válido durante 24 horas.

Para partes fallidas:

  1. Solicita una nueva URL firmada para el número de parte que falló
  2. Vuelve a subir solo esa parte
  3. Continúa con el paso de completar cuando todas las partes estén subidas