Upload multipart
Pour les gros fichiers vidéo (plus de 100 Mo), nous te recommandons d’utiliser un téléchargement multipart. Cette méthode découpe ton fichier en morceaux plus petits téléchargés en parallèle, ce qui améliore la fiabilité et les performances pour les gros fichiers.
Le téléchargement multipart est recommandé pour les fichiers de plus de 100 Mo et prend en charge des fichiers jusqu’à 60 Go.
Pour une implémentation plus simple, envisage la bibliothèque Uppy, qui gère le découpage, les nouvelles tentatives et le suivi de progression automatiquement.
Vue d’ensemble
Le processus de téléchargement multipart comporte quatre étapes :
- Initialiser — Créer un objet vidéo et demander un téléchargement multipart
- Obtenir des URL signées — Demander des URL pré-signées pour chaque partie (par lots pour l’efficacité)
- Téléverser les parties — Téléverser chaque segment vers son URL signée
- Finaliser — Indiquer que toutes les parties ont été téléchargées
Initialisation téléchargement multipart
Crée un objet vidéo en envoyant une requête PUT vers /videos/upload avec 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
}'Réponse
{
"videoId": "[VIDEO_ID]",
"title": "Your video title",
"multipartUpload": {
"uploadId": "[UPLOAD_ID]",
"key": "[S3_KEY]"
}
}Conserve les valeurs uploadId et key — tu en auras besoin pour toutes les requêtes suivantes.
Obtenir URL signées pour les parties
Avant de télécharger les parties, tu dois obtenir des URL pré-signées. Pour l’efficacité, demande les URL par lots plutôt qu’une par une.
Requête par lot (recommandée)
Demande plusieurs URL signées en une fois via l’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}'Réponse
{
"parts": [
{ "partNumber": 1, "url": "[SIGNED_URL_FOR_PART_1]" },
{ "partNumber": 2, "url": "[SIGNED_URL_FOR_PART_2]" }
]
}Requête d’une seule partie (secours)
Si tu as besoin d’une URL pour une partie précise, tu peux la demander individuellement.
CURL
curl "https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/[UPLOAD_ID]/[PART_NUMBER]?key=[S3_KEY]" \
-H "Authorization: Bearer YOUR_TOKEN"Téléversement des parties
Découpe ton fichier en segments (recommandé : 5 Mo à 100 Mo par partie) et télécharge chaque segment vers son URL signée correspondante avec une requête PUT.
Taille des parties : le téléchargement multipart impose une taille minimale de 5 Mo par partie (sauf pour la dernière). Nous recommandons des segments de 10 Mo pour un bon équilibre entre parallélisation et surcharge.
L’exemple ci-dessous suppose que tu as récupéré toutes les URL signées nécessaires. Pour les fichiers avec plus de 100 parties, tu devras obtenir les URL par lots. Voir Exemple complet ci-dessous pour gérer les gros fichiers.
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);
}Important : tu dois récupérer l’en-tête ETag de chaque réponse de téléchargement de partie. Ces valeurs sont nécessaires pour finaliser le téléchargement multipart.
Finalisation téléchargement multipart
Une fois toutes les parties téléchargées, envoie une requête de finalisation avec la liste des parties et leurs ETag.
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\"" }
]
}'Pour les téléchargements de plus de 100 parties, tu peux utiliser fetchPartsFromStorage: true au lieu de passer le tableau parts. Le serveur récupère alors automatiquement les informations sur les parties.
// 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
})
}
);Processus d’encodage
Une fois le téléchargement multipart terminé, la vidéo est encodée. Ce processus peut prendre du temps selon la taille de la vidéo et la complexité de l’encodage.
Tu peux vérifier le statut d’encodage d’une vidéo en appelant l’endpoint /videos/[VIDEO_ID] comme décrit dans la section Obtenir une vidéo.
Exemple complet
Voici un exemple JavaScript complet qui implémente le téléchargement multipart avec suivi de progression :
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;
}Gestion des erreurs
Si un téléchargement échoue, tu peux réessayer des parties individuelles sans tout recommencer. L’uploadId reste valide pendant 24 heures.
Pour les parties en échec :
- Demande une nouvelle URL signée pour le numéro de partie concerné
- Télécharge à nouveau uniquement cette partie
- Poursuis avec l’étape de finalisation une fois toutes les parties téléchargées