Generate images and video
Create a still, edit it, animate it, and persist the generated media.
Covers Examples/Features/12-ImageGeneration.swift,
14-VideoGeneration.swift, and 23-WorkflowGuides.swift. You end up with a
small asset pipeline that turns one prompt into a still image and an animated
clip.
Generate the still
let image = try await generateImage(
model: OpenAIImageModel("gpt-image-2"),
prompt: "A paper boat drifting down a rainy street, cinematic",
size: "1024x1024"
)
let imageURL = outputDirectory.appendingPathComponent("paper-boat.png")
try image.image.write(to: imageURL)image.image is the first result. Use image.images when requesting multiple
variants.
Edit an existing image
Passing source images through generateImage switches providers that support
editing, such as OpenAI, to their edit flow:
let edited = try await generateImage(
model: OpenAIImageModel("gpt-image-2"),
prompt: "Make the scene nighttime and add warm window light",
images: [ImageContent(data: image.image, mediaType: "image/png")]
)Animate the still
let video = try await generateVideo(
model: XaiVideoModel("grok-imagine-video-1.5"),
prompt: "The boat drifts forward while rain ripples across the street",
image: ImageContent(data: image.image, mediaType: "image/png"),
aspectRatio: "16:9",
duration: 6
)Video providers render asynchronously. Their model types handle job polling, so this call returns only when the provider reports a completed clip or an error.
Handle inline bytes and URLs
Providers may return either form:
if let bytes = video.video {
try bytes.write(to: outputDirectory.appendingPathComponent("paper-boat.mp4"))
} else if let remoteURL = video.urls.first {
print("ready at", remoteURL)
}Copy remote media into storage you control if provider URLs are temporary. Avoid holding large generated files in memory longer than necessary.
Swap media providers
The workflow functions stay unchanged when the model changes:
let stillModel: any ImageModel = FalImageModel("fal-ai/flux/schnell")
let videoModel: any VideoModel = LumaVideoModel("ray-2")Size, aspect ratio, duration, and provider-native options still depend on the selected model.
Final code
import AI
import Foundation
func createClip(in outputDirectory: URL) async throws -> GenerateVideoResult {
let image = try await generateImage(
model: OpenAIImageModel("gpt-image-2"),
prompt: "A paper boat drifting down a rainy street, cinematic",
size: "1024x1024"
)
let imageURL = outputDirectory.appendingPathComponent("paper-boat.png")
try image.image.write(to: imageURL)
return try await generateVideo(
model: XaiVideoModel("grok-imagine-video-1.5"),
prompt: "The boat drifts forward while rain ripples across the street",
image: ImageContent(data: image.image, mediaType: "image/png"),
aspectRatio: "16:9",
duration: 6
)
}See Image generation and Video generation for every provider and option.