Le helper uploadFile du SDK est la voie facile, mais il ne reprend pas entre
appels (un upload interrompu repart du premier chunk). Quand il vous faut une
reprise robuste — réseau instable, fichiers de plusieurs Go, uploads qui
survivent à un rechargement de page —, pilotez le transfert avec un client
TUS éprouvé. Voici un court tuto, pour le navigateur et pour
le serveur.
La clé à comprendre : deux niveaux d’auth
Le flux d’upload Videas a deux étapes avec des sécurités différentes :
| Étape | Endpoint | Clé API requise ? | Où |
|---|---|---|---|
| 1. Créer la session | POST /upload/ (Write Assets) |
Oui — clé secrète sk_ |
Serveur uniquement |
| 2. Transférer les octets | PATCH/HEAD sur la Location renvoyée |
Non — la Location est une URL-capacité secrète |
Serveur ou navigateur |
La Location renvoyée est donc une URL d’upload secrète et à usage unique :
quiconque la détient peut envoyer les octets, sans clé API. C’est ce qui rend
possibles des uploads navigateur sûrs : votre serveur crée la session, le
navigateur ne voit jamais que l’URL-capacité.
Uploads depuis le navigateur (pattern recommandé)
Ne mettez jamais votre clé sk_ dans le navigateur. À la place :
1. Votre serveur crée la session (il détient la clé) et renvoie la
Location. Voir Envoyer avec l’API REST → étape 1 ;
avec le SDK c’est videas.upload.createSession(...). Exposez un petit endpoint :
// serveur — POST /api/upload-session { filename, size }
app.post('/api/upload-session', async (req, res) => {
const created = await videas.upload.createSession({
headers: {
'Tus-Resumable': '1.0.0',
'Upload-Length': String(req.body.size),
// paires clé <base64(valeur)> ; filename + workspace_uid sont requis
'Upload-Metadata': `filename ${btoa(req.body.filename)},workspace_uid ${btoa('ws_123')}`,
},
})
res.json({ location: created.location }) // l'URL-capacité — sûre pour le navigateur
})
2. Le navigateur transfère vers cette URL avec tus-js-client — par chunks, reprenable, sans clé :
<script type="module">
import * as tus from 'https://cdn.jsdelivr.net/npm/tus-js-client@4/+esm'
const file = input.files[0]
const { location } = await (await fetch('/api/upload-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ filename: file.name, size: file.size }),
})).json()
const upload = new tus.Upload(file, {
uploadUrl: location, // reprendre une session déjà créée
chunkSize: 32 * 1024 * 1024, // ≤ 50 Mio (limite serveur par chunk)
retryDelays: [0, 3000, 10000], // réessais automatiques avec back-off
onProgress: (sent, total) => console.log(`${Math.round((sent / total) * 100)} %`),
onSuccess: () => console.log('terminé'),
onError: (err) => console.error(err),
})
// Reprendre si ce fichier a déjà été partiellement envoyé, sinon démarrer.
upload.findPreviousUploads().then((prev) => {
if (prev.length) upload.resumeFromPreviousUpload(prev[0])
upload.start()
})
</script>
tus-js-client fait un HEAD sur la Location pour connaître l’offset courant,
puis PATCH uniquement les octets manquants — une coupure (ou un rechargement
de page) reprend au lieu de tout recommencer.
Uploads côté serveur (Node)
Côté serveur la clé est en sécurité : laissez tus-js-client faire les deux étapes — pointez-le sur l’endpoint de création avec votre clé et les métadonnées requises :
import * as tus from 'tus-js-client'
import { createReadStream, statSync } from 'node:fs'
const path = 'film.mp4'
const upload = new tus.Upload(createReadStream(path), {
endpoint: 'https://api.videas.com/api/external/v1/upload/',
headers: { Authorization: `Bearer ${process.env.VIDEAS_API_KEY}` },
uploadSize: statSync(path).size,
metadata: { filename: 'film.mp4', workspace_uid: 'ws_123', content_type: 'video/mp4' },
chunkSize: 32 * 1024 * 1024,
retryDelays: [0, 3000, 10000],
onSuccess: () => console.log('terminé'),
})
upload.start()
Uploads côté serveur (Python)
Avec tus-py-client (pip install tuspy) :
import os
from tusclient import client
tus = client.TusClient(
"https://api.videas.com/api/external/v1/upload/",
headers={"Authorization": f"Bearer {os.environ['VIDEAS_API_KEY']}"},
)
uploader = tus.uploader(
"film.mp4",
chunk_size=32 * 1024 * 1024, # ≤ 50 Mio
metadata={"filename": "film.mp4", "workspace_uid": "ws_123"},
)
uploader.upload() # reprenable : relancez pour continuer un upload interrompu
Après l’upload
Comme pour tout upload : vous obtenez un asset_uid, puis la vidéo est traitée
de façon asynchrone — interrogez GET /assets/{uid}/ jusqu’à status: ready.
Voir Comment fonctionnent les envois.
Lequel choisir ?
- Simple, fichiers petits/moyens, côté serveur → le helper
uploadFiledu SDK (Envoyer avec le SDK). - Uploads navigateur → le serveur crée la session, le navigateur utilise
tus-js-client avec
uploadUrl(ci-dessus). - Reprise robuste / très gros fichiers → un client TUS (tus-js-client, tuspy).