Реализация AI-генерации изображений (Midjourney API) в мобильном приложении
У Midjourney нет официального публичного API — это первое, что нужно понять. Все «Midjourney API» на рынке — это либо неофициальные обёртки над Discord-ботом (MidJourney API proxy), либо альтернативные провайдеры с похожим качеством (Ideogram, Leonardo.ai). Выбор подхода зависит от требований к стабильности и юридической чистоте.
Варианты интеграции
Неофициальные прокси
Сервисы типа useapi.net, midjourney-api.thenextleg.io, imaginesoftware.io предоставляют REST API поверх собственных Discord-аккаунтов с Midjourney. Технически работает, но:
- Нарушает ToS Midjourney (риск бана аккаунта)
- Нестабильность при обновлениях Discord/Midjourney
- Нет SLA
- Результаты зависят от версии бота у провайдера
Для прототипов и внутренних инструментов — приемлемо. Для продакшена — рискованно.
Альтернативы с аналогичным качеством
Ideogram v2 — соизмеримое с Midjourney качество для художественных стилей, плюс отличный текст внутри изображений (слабое место MJ). Официальный API.
Leonardo.ai — богатая библиотека стилей, ControlNet, motion (видео). Официальный API.
Flux (FAL.ai) — Flux Pro/Ultra от Black Forest Labs, качество на уровне MJ v6, официальный API через FAL.
Для большинства продуктовых задач Flux Pro на FAL — лучший выбор: стабильный API, высокое качество, приемлемые цены.
Интеграция через прокси API (useapi.net)
Если клиент настаивает именно на Midjourney:
class MidjourneyProxyService(private val apiKey: String) {
private val client = OkHttpClient.Builder()
.readTimeout(300, TimeUnit.SECONDS) // MJ генерирует до 3–4 минут
.build()
suspend fun imagine(prompt: String): String = withContext(Dispatchers.IO) {
val body = JSONObject().apply {
put("prompt", prompt)
}.toString().toRequestBody("application/json".toMediaType())
val request = Request.Builder()
.url("https://api.useapi.net/v2/jobs/imagine")
.header("Authorization", "Bearer $apiKey")
.post(body)
.build()
val response = client.newCall(request).execute()
val json = JSONObject(response.body!!.string())
json.getString("jobid") // Получаем jobid для polling
}
suspend fun getResult(jobId: String): MidjourneyResult? = withContext(Dispatchers.IO) {
val request = Request.Builder()
.url("https://api.useapi.net/v2/jobs/?jobid=$jobId")
.header("Authorization", "Bearer $apiKey")
.get()
.build()
val response = client.newCall(request).execute()
val json = JSONObject(response.body!!.string())
when (json.optString("status")) {
"completed" -> {
val attachments = json.getJSONArray("attachments")
MidjourneyResult.Success(attachments.getJSONObject(0).getString("url"))
}
"failed" -> MidjourneyResult.Failed(json.optString("error"))
else -> null // ещё в процессе
}
}
}
Midjourney генерирует сетку 2x2 изображения. После получения результата пользователь может выбрать один вариант (upscale) или запросить вариации. Это дополнительные API-вызовы (/v2/jobs/button с action U1–U4 или V1–V4).
Интеграция Flux через FAL.ai (рекомендуемый подход)
struct FalFluxService {
private let baseURL = "https://fal.run/fal-ai/flux-pro"
func generate(prompt: String) async throws -> URL {
var request = URLRequest(url: URL(string: baseURL)!)
request.httpMethod = "POST"
request.setValue("Key \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body: [String: Any] = [
"prompt": prompt,
"image_size": "square_hd",
"num_inference_steps": 28,
"guidance_scale": 3.5,
"num_images": 1,
"enable_safety_checker": true
]
request.httpBody = try JSONSerialization.data(withJSONObject: body)
let (data, _) = try await URLSession.shared.data(for: request)
let response = try JSONDecoder().decode(FalResponse.self, from: data)
return URL(string: response.images[0].url)!
}
}
FAL возвращает результат синхронно (или через очередь при нагрузке). Задержка Flux Pro — 5–10 секунд для square_hd.
Prompt-параметры Midjourney
Если работаешь с MJ через прокси, промпты имеют специфичный синтаксис:
portrait photo of astronaut in forest --ar 3:4 --v 6 --style raw --stylize 100
--ar — aspect ratio (16:9, 3:4, 1:1)
--v 6 — версия модели
--style raw — менее стилизованный результат
--stylize 0–1000 — степень стилизации (250 дефолт)
--no text, watermark — negative prompt
--seed 12345 — воспроизводимость
Через обычные API (Ideogram, FAL) эти параметры передаются нативными полями запроса.
UX при долгой генерации
Midjourney через прокси: 60–180 секунд. Flux: 5–15 секунд.
Для длинного ожидания — polling каждые 5 секунд с анимированным индикатором. Не чаще: провайдеры могут throttle при частых запросах. Показывай elapsed time («Генерируется... 45 сек»), это снижает тревогу пользователя.
Сроки
Интеграция прокси-API (useapi.net или аналог) с polling и базовым UI — 4–6 дней. Flux/Ideogram с нативным API, upscale/variations, галерея — 10–14 дней.







