-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add create generation method for LumaAI
- Loading branch information
1 parent
fa5a627
commit 6e5a584
Showing
3 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// | ||
// LumaAIError.swift | ||
// ShipinKit | ||
// | ||
// Created by Rudrank Riyam on 10/13/24. | ||
// | ||
|
||
|
||
|
||
/// An error type representing errors from the Luma AI client. | ||
public enum LumaAIError: Error { | ||
/// An HTTP error with a status code. | ||
case httpError(statusCode: Int) | ||
/// A decoding error occurred. | ||
case decodingError(underlying: Error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// | ||
// LumaAIGenerationResponse.swift | ||
// ShipinKit | ||
// | ||
// Created by Rudrank Riyam on 10/13/24. | ||
// | ||
|
||
import Foundation | ||
|
||
/// Represents the response from the Luma AI generation API. | ||
public struct LumaAIGenerationResponse: Codable { | ||
public let id: String | ||
public let state: String | ||
public let failureReason: String? | ||
public let createdAt: String | ||
public let assets: LumaAIAssets | ||
public let version: String | ||
public let request: LumaAIGenerationRequest | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case id | ||
case state | ||
case failureReason = "failure_reason" | ||
case createdAt = "created_at" | ||
case assets | ||
case version | ||
case request | ||
} | ||
} | ||
|
||
/// Contains the assets returned by the Luma AI generation API. | ||
public struct LumaAIAssets: Codable { | ||
public let video: String | ||
} | ||
|
||
/// Represents the original request sent to the Luma AI generation API. | ||
public struct LumaAIGenerationRequest: Codable { | ||
public let prompt: String | ||
public let aspectRatio: String | ||
public let loop: Bool | ||
public let keyframes: [String: LumaAIKeyframeData] | ||
public let callbackURL: String? | ||
|
||
enum CodingKeys: String, CodingKey { | ||
case prompt | ||
case aspectRatio = "aspect_ratio" | ||
case loop | ||
case keyframes | ||
case callbackURL = "callback_url" | ||
} | ||
} | ||
|
||
/// Represents keyframe data in the generation request. | ||
public struct LumaAIKeyframeData: Codable { | ||
public let type: String | ||
public let url: String? | ||
public let id: String? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// | ||
// LumaAIClient.swift | ||
// ShipinKit | ||
// | ||
// Created by Rudrank Riyam on 10/13/24. | ||
// | ||
|
||
import Foundation | ||
|
||
/// A client for interacting with the Luma AI API. | ||
public class LumaAIClient { | ||
private let apiKey: String | ||
private let session: URLSession | ||
private let baseURL = URL(string: "https://api.lumalabs.ai")! | ||
|
||
/// Initializes a new instance of `LumaAIClient` | ||
/// | ||
/// - Parameters: | ||
/// - apiKey: Your Luma AI API key. | ||
/// - session: The URLSession to use for network requests. Defaults to `URLSession.shared`. | ||
public init(apiKey: String, session: URLSession = .shared) { | ||
self.apiKey = apiKey | ||
self.session = session | ||
} | ||
|
||
/// Initiates a generation request to the Luma AI API. | ||
/// | ||
/// - Parameters: | ||
/// - prompt: The prompt for the generation. | ||
/// - aspectRatio: The aspect ratio of the generated content. Defaults to "16:9". | ||
/// - loop: Whether the generated content should loop. | ||
/// - keyframes: A dictionary of keyframes. | ||
/// - callbackURL: The callback URL to receive generation updates. | ||
/// | ||
/// - Returns: A `GenerationResponse` containing the result of the generation. | ||
public func createGeneration(prompt: String, aspectRatio: String = "16:9", loop: Bool, keyframes: [String: LumaAIKeyframeData], callbackURL: String? = nil) async throws -> LumaAIGenerationResponse { | ||
let url = baseURL.appendingPathComponent("/dream-machine/v1/generations") | ||
var request = URLRequest(url: url) | ||
request.httpMethod = "POST" | ||
request.timeoutInterval = 10 | ||
request.addValue("application/json", forHTTPHeaderField: "accept") | ||
request.addValue("application/json", forHTTPHeaderField: "content-type") | ||
request.addValue("Bearer \(apiKey)", forHTTPHeaderField: "authorization") | ||
|
||
let requestBody = LumaAIGenerationRequest(prompt: prompt, aspectRatio: aspectRatio, loop: loop, keyframes: keyframes, callbackURL: callbackURL) | ||
let encoder = JSONEncoder() | ||
encoder.keyEncodingStrategy = .convertToSnakeCase | ||
let bodyData = try encoder.encode(requestBody) | ||
request.httpBody = bodyData | ||
|
||
let (data, response) = try await session.data(for: request) | ||
|
||
if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) { | ||
throw LumaAIError.httpError(statusCode: httpResponse.statusCode) | ||
} | ||
|
||
let decoder = JSONDecoder() | ||
decoder.keyDecodingStrategy = .convertFromSnakeCase | ||
do { | ||
let generationResponse = try decoder.decode(LumaAIGenerationResponse.self, from: data) | ||
return generationResponse | ||
} catch { | ||
throw LumaAIError.decodingError(underlying: error) | ||
} | ||
} | ||
} |