Upload wieloczęściowy
Dla dużych plików wideo (powyżej 100 MB) polecamy przesyłanie wieloczęściowe. Metoda dzieli plik na mniejsze fragmenty przesyłane równolegle, co daje lepszą niezawodność i wydajność dla dużych plików.
Przesyłanie wieloczęściowe zalecamy dla plików większych niż 100 MB; obsługuje pliki do 60 GB.
Dla prostszej implementacji rozważ bibliotekę Uppy, która sama dzieli plik na fragmenty, ponawia próby i śledzi postęp.
Przegląd
Proces przesyłania wieloczęściowego składa się z czterech kroków:
- Inicjalizacja — utwórz obiekt wideo i poproś o przesyłanie wieloczęściowe
- Pobranie podpisanych adresów URL — poproś o wstępnie podpisane adresy URL dla każdej części (partiiami, dla wydajności)
- Przesłanie części — prześlij każdy fragment na jego podpisany adres URL
- Zakończenie — zasygnalizuj, że wszystkie części zostały przesłane
Inicjalizacja przesyłania wieloczęściowego
Utwórz obiekt wideo, wysyłając żądanie PUT na /videos/upload z 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
}'Odpowiedź
{
"videoId": "[VIDEO_ID]",
"title": "Your video title",
"multipartUpload": {
"uploadId": "[UPLOAD_ID]",
"key": "[S3_KEY]"
}
}Zapisz wartości uploadId i key — będziesz ich potrzebować we wszystkich kolejnych żądaniach.
Pobieranie podpisanych adresów URL dla części
Zanim prześlesz części, musisz uzyskać wstępnie podpisane adresy URL. Dla wydajności żądaj ich partiami, a nie pojedynczo.
Żądanie wsadowe (zalecane)
Poproś o podpisane adresy URL dla wielu części naraz, używając endpointu 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}'Odpowiedź
{
"parts": [
{ "partNumber": 1, "url": "[SIGNED_URL_FOR_PART_1]" },
{ "partNumber": 2, "url": "[SIGNED_URL_FOR_PART_2]" }
]
}Pojedyncza część (fallback)
Jeśli potrzebujesz adresu URL dla konkretnej części, możesz poprosić o niego osobno.
CURL
curl "https://app.ignitevideo.cloud/api/videos/upload/s3/multipart/[UPLOAD_ID]/[PART_NUMBER]?key=[S3_KEY]" \
-H "Authorization: Bearer YOUR_TOKEN"Przesyłanie części
Podziel plik na fragmenty (zalecane: 5–100 MB na część) i prześlij każdy fragment na odpowiadający mu podpisany adres URL żądaniem PUT.
Rozmiar części: przesyłanie wieloczęściowe wymaga minimum 5 MB na część (z wyjątkiem ostatniej). Polecamy fragmenty po 10 MB jako kompromis między równoległością a narzutem.
Poniższy przykład zakłada, że masz już pobrane wszystkie potrzebne podpisane adresy URL. Dla plików z ponad 100 częściami musisz pobierać adresy partiami. Zobacz kompletny przykład poniżej, jak obsłużyć duże pliki.
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);
}Ważne: musisz zebrać nagłówek ETag z odpowiedzi na przesłanie każdej części. Są one wymagane, żeby dokończyć przesyłanie wieloczęściowe.
Zakończenie przesyłania wieloczęściowego
Gdy wszystkie części są przesłane, wyślij żądanie zakończenia z listą części i ich ETagami.
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\"" }
]
}'Dla przesłań z ponad 100 częściami możesz użyć fetchPartsFromStorage: true zamiast przekazywać tablicę parts. Serwer sam pobierze informacje o częściach.
// 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
})
}
);Proces kodowania
Po zakończeniu przesyłania wieloczęściowego wideo zostanie poddane kodowaniu. Może to zająć trochę czasu w zależności od rozmiaru wideo i złożoności kodowania.
Status kodowania sprawdzisz, wywołując endpoint /videos/[VIDEO_ID] zgodnie z sekcją pobieranie wideo.
Kompletny przykład
Poniżej pełny przykład w JavaScript z przesyłaniem wieloczęściowym i śledzeniem postępu:
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;
}Obsługa błędów
Jeśli przesyłanie się nie powiedzie, możesz ponowić pojedyncze części bez restartu całego uploadu. uploadId pozostaje ważny przez 24 godziny.
Dla nieudanych części:
- Poproś o nowy podpisany adres URL dla numeru nieudanej części
- Prześlij ponownie tylko tę część
- Przejdź do kroku zakończenia, gdy wszystkie części będą przesłane