rw-integrate-uploads

Par runwayml · skills

Aider les utilisateurs à téléverser des fichiers locaux vers Runway pour les utiliser comme entrées dans les modèles de génération

npx skills add https://github.com/runwayml/skills --skill rw-integrate-uploads

Intégrer les uploads

CONDITION PRÉALABLE : Exécutez d'abord +rw-check-compatibility. Exécutez +rw-fetch-api-reference pour charger la dernière référence API avant d'intégrer. Nécessite +rw-setup-api-key pour les credentials API.

Aidez les utilisateurs à télécharger des fichiers locaux (images, vidéos, audio) vers le stockage éphémère de Runway pour les utiliser comme entrées des modèles de génération.

Quand utiliser les uploads

Utilisez l'API Uploads quand :

  • L'utilisateur a un fichier local (pas une URL publique) qu'il souhaite utiliser comme entrée
  • Le fichier dépasse les limites de taille des data URI (5 Mo pour les images, 16 Mo pour la vidéo/audio)
  • L'URL du fichier ne respecte pas les exigences d'URL de Runway (HTTPS, en-têtes corrects, pas de redirects)

Vous n'avez PAS besoin d'uploads quand :

  • L'asset est déjà à une URL HTTPS publique avec les bons en-têtes
  • L'asset est assez petit pour un data URI (< 5 Mo image, < 16 Mo vidéo)

Comment ça fonctionne

  1. Demandez un emplacement d'upload éphémère → obtenez une URL de chargement présignée et des champs de formulaire
  2. Chargez le fichier vers l'URL présignée
  3. Utilisez l'URI runway:// retourné comme entrée à n'importe quel endpoint de génération

Les URIs runway:// sont valides pendant 24 heures.

Upload SDK (Recommandé)

Node.js

import RunwayML from '@runwayml/sdk';
import fs from 'fs';

const client = new RunwayML();

// Upload depuis un flux de fichier
const upload = await client.uploads.createEphemeral(
  fs.createReadStream('/path/to/image.jpg')
);

// Utilisez l'URI runway:// dans n'importe quel appel de génération
const task = await client.imageToVideo.create({
  model: 'gen4.5',
  promptImage: upload.runwayUri,
  promptText: 'The scene comes to life',
  ratio: '1280:720',
  duration: 5
}).waitForTaskOutput();

Le SDK Node.js accepte :

  • fs.ReadStream — flux de fichiers
  • Objets File — issus des APIs web
  • Objets Blob
  • Buffer / ArrayBuffer / tableaux typés
  • Objets Response — issus de fetch()
  • Itérables asynchrones

Python

from runwayml import RunwayML
from pathlib import Path

client = RunwayML()

# Upload depuis un chemin de fichier
upload = client.uploads.create_ephemeral(
    Path('/path/to/image.jpg')
)

# Utilisez l'URI runway://
task = client.image_to_video.create(
    model='gen4.5',
    prompt_image=upload.runway_uri,
    prompt_text='The scene comes to life',
    ratio='1280:720',
    duration=5
).wait_for_task_output()

Le SDK Python accepte :

  • Objets pathlib.Path
  • Objets IOBase (objets de type fichier)
  • Tuples de deux éléments (filename, content)

Upload via API REST (Manuel)

Si vous n'utilisez pas le SDK, le flux d'upload a trois étapes :

Étape 1 : Créer un emplacement d'upload

const response = await fetch('https://api.dev.runwayml.com/v1/uploads', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.RUNWAYML_API_SECRET}`,
    'X-Runway-Version': '2024-11-06',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    filename: 'image.jpg',
    type: 'ephemeral'
  })
});

const { uploadUrl, fields, runwayUri } = await response.json();

Étape 2 : Charger le fichier en utilisant l'URL présignée

const formData = new FormData();

// Ajoutez d'abord tous les champs de formulaire présignés
for (const [key, value] of Object.entries(fields)) {
  formData.append(key, value);
}

// Ajoutez le fichier en dernier
formData.append('file', fileBuffer, 'image.jpg');

await fetch(uploadUrl, {
  method: 'POST',
  body: formData
});

Étape 3 : Utiliser l'URI runway://

const task = await fetch('https://api.dev.runwayml.com/v1/image_to_video', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.RUNWAYML_API_SECRET}`,
    'X-Runway-Version': '2024-11-06',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    model: 'gen4.5',
    promptImage: runwayUri,
    promptText: 'Animate this scene',
    ratio: '1280:720',
    duration: 5
  })
});

Contraintes d'upload

Contrainte Valeur
Taille minimale du fichier 512 octets
Taille maximale du fichier 200 Mo
Validité de l'URI 24 heures
Demande des crédits Oui (doit avoir acheté des crédits)

Modèle d'intégration

Express.js — Endpoint d'upload avec génération de fichier

import RunwayML from '@runwayml/sdk';
import express from 'express';
import multer from 'multer';

const client = new RunwayML();
const app = express();
const upload = multer({ storage: multer.memoryStorage() });

app.post('/api/image-to-video', upload.single('image'), async (req, res) => {
  try {
    // Chargez le fichier de l'utilisateur vers Runway
    const runwayUpload = await client.uploads.createEphemeral(req.file.buffer);

    // Utilisez le fichier chargé pour la génération vidéo
    const task = await client.imageToVideo.create({
      model: 'gen4.5',
      promptImage: runwayUpload.runwayUri,
      promptText: req.body.prompt || 'Animate this image',
      ratio: '1280:720',
      duration: 5
    }).waitForTaskOutput();

    res.json({ videoUrl: task.output[0] });
  } catch (error) {
    console.error('Generation failed:', error);
    res.status(500).json({ error: error.message });
  }
});

Next.js — Upload + Génération

// app/api/image-to-video/route.ts
import RunwayML from '@runwayml/sdk';
import { NextRequest, NextResponse } from 'next/server';

const client = new RunwayML();

export async function POST(request: NextRequest) {
  const formData = await request.formData();
  const imageFile = formData.get('image') as File;
  const prompt = formData.get('prompt') as string;

  try {
    // Chargez le fichier vers Runway
    const upload = await client.uploads.createEphemeral(imageFile);

    // Générez une vidéo à partir de l'image chargée
    const task = await client.imageToVideo.create({
      model: 'gen4.5',
      promptImage: upload.runwayUri,
      promptText: prompt || 'Animate this image',
      ratio: '1280:720',
      duration: 5
    }).waitForTaskOutput();

    return NextResponse.json({ videoUrl: task.output[0] });
  } catch (error) {
    return NextResponse.json(
      { error: error instanceof Error ? error.message : 'Failed' },
      { status: 500 }
    );
  }
}

FastAPI — Upload + Génération

from fastapi import FastAPI, UploadFile, Form, HTTPException
from runwayml import RunwayML

app = FastAPI()
client = RunwayML()

@app.post("/api/image-to-video")
async def image_to_video(image: UploadFile, prompt: str = Form("Animate this image")):
    try:
        # Chargez vers Runway
        content = await image.read()
        upload = client.uploads.create_ephemeral((image.filename, content))

        # Générez une vidéo
        task = client.image_to_video.create(
            model="gen4.5",
            prompt_image=upload.runway_uri,
            prompt_text=prompt,
            ratio="1280:720",
            duration=5
        ).wait_for_task_output()

        return {"video_url": task.output[0]}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

Conseils

  • Chargez toujours les fichiers locaux avant de les passer aux endpoints de génération. N'essayez pas de passer des chemins de fichiers locaux — ça ne fonctionnera pas.
  • Les URIs runway:// expirent après 24 heures. Si vous devez réutiliser un asset, chargez-le à nouveau.
  • Le SDK gère automatiquement le flux d'URL présignée — préférez le SDK aux appels REST manuels.
  • Pour les modèles nécessitant une entrée d'image/vidéo (image-to-video, video-to-video, character performance), chargez d'abord l'asset, puis passez l'URI runway://.
  • Maximum 200 Mo par fichier via uploads — plus que les limites d'URL (16 Mo) ou de data URI (5 Mo).

Skills similaires