L'intelligence artificielle au service de l'art

Comment utiliser l’API de Midjourney avec Python ?

Dans cet article je vous explique comment utiliser l’API de Midjourney dans vos codes Python grâce au service MyMidjourney.

La génération d’images est devenue en quelques mois une des techniques les plus performantes et abouties en IA générative. Son principe est simple : transformer un texte (ou un prompt) en image.

De nombreux outils sont disponibles sur le marché, comme Dalle-3, Stable diffusion ou encore Leonardo. Mais le plus performant et impressionnant aujourd’hui est de loin Midjourney.

La plupart des outils mentionnés sont disponibles sous forme d’API faciles à intégrer en Python. Dalle-3 via la librairie openai. De même stable diffusion et Leonardo sont disponibles sans problème avec des API officielles.

Midjourney est utilisable exclusivement sur Discord et il n’y a ni d’API ni de web app accessible pour cet outil. Une stratégie assez curieuse de la part des fondateurs de Midjourney mais qui a quand même l’air de bien payer pour le moment.

Certains services ont émergés pour résoudre ce problème et proposent des API non-officielle de Midjourney qui sont codées à l’aide de bot qui permettent l’automatisation de l’utilisation de Discord.

Fonctionnement de l’API de Midjourney

L’API de Midjourney proposée par MyMidjourney fonctionne via l’automatisation de tâches sur la plateforme Discord.

Lorsqu’une requête est envoyée c’est le comportement d’un utilisateur de Midjourney qui est simulé. Exactement comme si quelqu’un tapait sur Discord la requête « /imagine prompt« .

Il faut ensuite simuler le fait d’appuyer sur un des boutons de l’UI :

  • U1, U2, U3, U4, pour upscaler une des images
  • V1, V2, V3, V4, pour faire varier une des images

Une fois que ces étapes sont réalisées il ne reste plus qu’à récupérer le lien de l’image et la télécharger.

Pricing de l’API de Midjourney

La tarification de MyMidjourney offre aux utilisateurs une gamme de plans adaptés à leurs besoins, avec des fréquences de paiement mensuelles ou annuelles.

Le Plan Standard à 30 $ par mois fournit un point de départ complet pour explorer l’API de Midjourney, offrant des capacités de génération d’images complètes avec jusqu’à 100 générations par mois, un processus d’installation facile et des instructions d’utilisation claires.

Pour ceux qui ont des besoins plus importants pour l’API de Midjourney, le Plan Pro à 45 $ par mois débloque des fonctionnalités avancées telles que des générations illimitées, la possibilité d’utiliser son propre compte Discord/Midjourney, et la gestion de plusieurs comptes pour une meilleure gestion.

MyMidjourney offre la possibilité d’avoir un serveur dédié qui offre un service prioritaire avec une infrastructure dédiée, un support rapide et efficace, et des files d’attente de traitement plus rapides pour des générations d’images accélérées.

pricing de l'API de Midjourney

Les utilisateurs peuvent choisir d’utiliser leur propre compte Midjourney ou de bénéficier de l’assistance de MyMidjourney pour en configurer un. Il convient de noter que des frais supplémentaires s’appliquent lorsque plusieurs comptes Discord sont liés au système.

Enfin, les quotas de génération d’images varient en fonction du plan Midjourney de l’utilisateur lors de la liaison, avec une limite de 600 générations par mois dans le cas contraire.

Utilisation de l’API de Midjourney avec Python

Vous allez avoir besoin d’une clé API pour lancer des requêtes sur MyMidjourney. Il faudra pour cela créer votre compte sur leur site. Puis cliquer sur votre image de profil en haut à droite, puis « Setup » :

Rubrique setup MyMidjourney

Une fois dans la page setup vous trouverez la rubrique « Your MyMidjourney Token », c’est votre clé API. Copiez-là et garder la secrète (dans un fichier .env de préférence) :

Votre clé API pour l'API de Midjourney

Comme évoquer à la première partie, la génération d’une image se fait en plusieurs étapes. Ces étapes correspondent à plusieurs endpoints qu’il faut appeler un par un :

  • Le premier permet de lancer la génération de l’image :
    • Le endpoint : https://api.mymidjourney.ai/api/v1/midjourney/imagine
    • Il prend en entrée un prompt et nécessite votre clé API
    • Il vous renverra un id de génération qu’il faut conserver
  • Le second endpoint permet de vérifier le status de la génération :
    • Le endpoint : https://api.mymidjourney.ai/api/v1/midjourney/message/{message_id}
    • Il prend en entrée un message ID qui correspond à l’ID de la génération obtenu après l’appel du premier endpoint, et nécessite une clé API aussi
    • Ils vous renverra les informations sur le status de la génération (en attente, en cours, échec ou terminée)
  • Le troisième endpoint permet de simuler un clic comme lorsque l’on utilise Midjourney via Discord :
    • Le endpoint : https://api.mymidjourney.ai/api/v1/midjourney/button
    • Il prend en entrée le message id et le nom du bouton sur lequel on veut cliquer
    • Il renverra une réponse de status
  • Enfin, le dernier endpoint de l’API de Midjourney permet de récupérer l’URL de l’image générée
    • Le endpoint : https://api.mymidjourney.ai/api/v1/midjourney/message/{message_id}
    • Il prend en entrée le message id et renvoi l’URL de l’image générée

Pour coder ça en python, on commence par les imports et définir les liens des endpoints :

import requests
import time

# Constants
GENERATION_API_URL = "https://api.mymidjourney.ai/api/v1/midjourney/imagine"
RESULTS_API_URL = "https://api.mymidjourney.ai/api/v1/midjourney/message/"
BUTTON_API_URL = "https://api.mymidjourney.ai/api/v1/midjourney/button"

On va maintenant définir le header qui contient la clé API une bonne fois pour toutes :

AUTHORIZATION_TOKEN = "VOTRE CLÉ pour l'API de Midjourney"
# Headers for requests
HEADERS = {
    "Content-Type": "application/json",
    "Authorization": AUTHORIZATION_TOKEN
}

On écrit aussi, une bonne fois pour toutes, la fonction qui permet d’appeler les différents endpoints :

def make_request(url, method='get', data=None):
    try:
        if method == 'post':
            response = requests.post(url, json=data, headers=HEADERS)
        else:
            response = requests.get(url, headers=HEADERS)
        response.raise_for_status()
        print(f"Request successful: {response.json()}")
        return response.json()
    except requests.exceptions.RequestException as e:
        print(f"Request error: {e}")
        return None

Les appels des différents endpoints sont faits de cette manière :

# Lancer la génération
def launch_generation(prompt):
    data = {"prompt": prompt}
    response = make_request(GENERATION_API_URL, 'post', data)
    if response:
        print(f"Request successful: {response}")
        return response.get("messageId")
    else:
        print("Request failed")
        return None

# Récupérer de le status de génération
def get_status_from_message_id(message_id):
    url = RESULTS_API_URL + message_id
    response = make_request(url)
    if response:
        print(f"Request successful: {response}")
        return response.get("status")
    else:
        print("Request failed")
        return None

# Cliquer sur un bouton
def click_button(message_id, button):
    data = {
        "messageId": message_id,
        "button": button
    }
    response = make_request(BUTTON_API_URL, 'post', data)
    if response:
        print(f"Request successful: {response}")
        return response.get("messageId")
    else:
        print("Request failed")
        return None

# Récupérer l'URL de l'image
def get_image_from_message_id(message_id):
    url = RESULTS_API_URL + message_id
    response = make_request(url)
    if response:
        print(f"Request successful: {response}")
    else:
        print("Request failed")
    return response.get("uri") if response else None

Comme l’API de Midjourney n’a pas de webhook, on doit utiliser des boucles while et des time.sleep pour attendre la fin de chaque étape, j’ai décidé de le coder de cette manière :

def generate_image_my_midjourney(prompt):

    prompt += " --v 6.0 --ar 16:9"
    message_id = launch_generation(prompt)
    if not message_id:
        return "Failed to launch image generation"

    # Wait for the status to be 'DONE'
    while True:
        status = get_status_from_message_id(message_id)
        if status == "DONE":
            break

    # Click the button and wait for the new message ID
    message_id_after_click = None
    while not message_id_after_click:
        message_id_after_click = click_button(message_id, "U1")

    print("Sleeping 10 seconds")
    time.sleep(10)
    # Retrieve the final image URI
    uri = None
    while not uri:
        uri = get_image_from_message_id(message_id_after_click)

    return uri

À la première ligne j’ajoute :  » –v 6.0 –ar 16:9″ c’est la syntaxe qui permet de spécifier des paramètres à l’API de Midjourney pour la génération.

Ici par exemple je lui demande d’utiliser Midjourney V6 et de générer des images avec un ratio de 16:9.

Pour générer une image on va simplement appeler cette dernière fonction avec le prompt voulu et on récuperera en quelques secondes l’output sous forme d’URL :

generate_image_my_midjourney("Mbappé inside the Parc des Princes")

Si vous avez des problèmes de blocage de prompt trop régulièrement, vous pouvez mettre à jour la liste des mots bannis par l’API de Midjourney avec cette syntaxe :

import requests

# Bearer token for authorization
bearer_token = "VOTRE CLÉ API"

# URL for the API endpoint
url = 'https://api.mymidjourney.ai/api/v1/discord/banwords/save'

# Headers including the authorization token
headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {bearer_token}'
}

# Liste des mots que vous voulez bannir, la liste peut être vide comme ici
ban_words = [
]

# Data payload to be sent
payload = {
    'list': ban_words
}

# Making the POST request
response = requests.post(url, json=payload, headers=headers)

# Check if the request was successful
if response.status_code == 200:
    print("Ban list updated successfully!")
    print("Updated list:", response.json())
else:
    print("Failed to update ban list.")
    print("Status Code:", response.status_code)
    print("Response:", response.text)

Conclusion

Disclaimer : l’API de Midjourney que j’ai présenté ici n’est pas officielle et pensez à vérifier que les conditions d’utilisation de Midjourney et Discord vous permettent de l’utiliser.

Cette API est assez performante globalement et le pricing est plutôt raisonnable lorsque l’on compte l’utiliser assez régulièrement.

Je vous ai montré uniquement la génération d’image dans cet article mais sachez que toutes les fonctionnalités de Midjourney sont proposées sous forme d’API, comme l’inpainting par exemple.

L’expérience de developpement n’est pas optimale puisqu’on n’a pas de webhook disponible et on doit multiplier les appels vers les différents endpoints. Mais au final, quand on comprend le rôle de chaque endpoint on s’en sort plutôt bien.