Cours Vibe coding avec l'IA · Module 10: Clone de TikTok

Génération d'images par IA - DALL-E/Stable Diffusion

1 min de lecture

Générer des images avec l'IA.

OpenAI DALL-E

1npm install openai
1import OpenAI from 'openai';
2
3const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
4
5async function generateImage(prompt: string) {
6  const response = await openai.images.generate({
7    model: "dall-e-3",
8    prompt,
9    n: 1,
10    size: "1024x1024"
11  });
12
13  return response.data[0].url;
14}
15
16function ImageGenerator() {
17  const [prompt, setPrompt] = useState("");
18  const [imageUrl, setImageUrl] = useState("");
19  const [loading, setLoading] = useState(false);
20
21  const handleGenerate = async () => {
22    setLoading(true);
23    const url = await generateImage(prompt);
24    setImageUrl(url);
25    setLoading(false);
26  };
27
28  return (
29    <div>
30      <textarea
31        value={prompt}
32        onChange={(e) => setPrompt(e.target.value)}
33        placeholder="Décris l'image que tu veux générer..."
34        className="w-full border rounded p-3"
35      />
36      <button
37        onClick={handleGenerate}
38        disabled={loading}
39        className="bg-blue-600 text-white px-4 py-2 rounded"
40      >
41        {loading ? 'Génération...' : 'Générer l\'image'}
42      </button>
43      {imageUrl && <img src={imageUrl} alt="Generated" className="mt-4" />}
44    </div>
45  );
46}

À bientôt !

Code de cette leçon : App.jsx
1// Enregistreur de vidéo
2import { useState, useEffect } from 'react';
3
4export default function App() {
5  const [isRecording, setIsRecording] = useState(false);
6  const [duration, setDuration] = useState(0);
7  const maxDuration = 60;
8
9  useEffect(() => {
10    let interval;
11    if (isRecording) {
12      interval = setInterval(() => {
13        setDuration(d => {
14          if (d >= maxDuration) {
15            setIsRecording(false);
16            return d;
17          }
18          return d + 0.1;
19        });
20      }, 100);
21    } else {
22      setDuration(0);
23    }
24    return () => clearInterval(interval);
25  }, [isRecording]);
26
27  return (
28    <div className="h-screen bg-black flex flex-col">
29      {/* Aperçu de la vidéo */}
30      <div className="flex-1 relative bg-gradient-to-br from-purple-900 to-blue-900 flex items-center justify-center">
31        <div className="text-9xl">◆</div>
32
33        {/* Indicateur d'enregistrement */}
34        {isRecording && (
35          <div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
36            <div className="w-20 h-20 border-4 border-red-500 rounded-full animate-pulse"></div>
37          </div>
38        )}
39
40        {/* Indicateur de son */}
41        <div className="absolute top-4 right-4 bg-black/50 px-3 py-2 rounded-full text-white text-sm flex items-center gap-2">
42          Pirate's Anthem
43        </div>
44      </div>
45
46      {/* Commandes */}
47      <div className="bg-black border-t border-gray-800 p-6">
48        {/* Barre de durée */}
49        <div className="mb-6">
50          <div className="h-1 bg-gray-700 rounded-full overflow-hidden">
51            <div
52              className={`h-full transition-all ${isRecording ? 'bg-red-500' : 'bg-gray-500'}`}
53              style={{ width: `${(duration / maxDuration) * 100}%` }}
54            />
55          </div>
56          <div className="flex justify-between mt-2 text-xs text-gray-400">
57            <span>{duration.toFixed(1)}s</span>
58            <span>{maxDuration}s</span>
59          </div>
60        </div>
61
62        {/* Actions */}
63        <div className="flex items-center justify-around">
64          {/* Effets */}
65          <button className="flex flex-col items-center gap-1">
66            <div className="w-12 h-12 bg-gray-800 rounded-full flex items-center justify-center text-2xl">
67              ◆
68            </div>
69            <span className="text-xs text-white">Effets</span>
70          </button>
71
72          {/* Bouton d'enregistrement */}
73          <button
74            onClick={() => setIsRecording(!isRecording)}
75            className={`w-20 h-20 rounded-full border-4 flex items-center justify-center transition ${
76              isRecording ? 'border-red-500 bg-red-500' : 'border-white bg-transparent'
77            }`}
78          >
79            {isRecording && <div className="w-8 h-8 bg-white rounded"></div>}
80          </button>
81
82          {/* Sons */}
83          <button className="flex flex-col items-center gap-1">
84            <div className="w-12 h-12 bg-gray-800 rounded-full flex items-center justify-center text-2xl">
85              ◉
86            </div>
87            <span className="text-xs text-white">Sons</span>
88          </button>
89        </div>
90      </div>
91    </div>
92  );
93}

Tu as repéré une erreur dans cette leçon ?

Teste tes connaissances

Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.

  1. 1. À quoi sert OpenAI DALL-E selon la leçon ?

  2. 2. Quel nom de modèle le code de génération d'image utilise-t-il ?

Tâches pratiques dans le jeu

  • Tri horizontal

    Ordonne le début de l'appel de génération d'image OpenAI :

Articles utiles