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:
- Inicializar — Crear un objeto de video y solicitar una subida multiparte
- Obtener URLs firmadas — Solicitar URLs pre-firmadas para cada parte (por lotes para eficiencia)
- Subir partes — Subir cada trozo a su URL firmada
- 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
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
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
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.
JavaScript / Node.js
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
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:
- Solicita una nueva URL firmada para el número de parte que falló
- Vuelve a subir solo esa parte
- Continúa con el paso de completar cuando todas las partes estén subidas