Text was just the beginning. Modern AI understands images, audio, video, and combinations of all modalities.
Multimodal AI unlocks use cases impossible with text alone: visual search, document understanding, video analysis, voice assistants, and more. This guide covers what you need to know to build multimodal applications in production.
| Category | Input | Output | Examples |
|---|
| Vision-Language | Image + Text | Text | GPT-4V, Claude 3, Gemini |
| Text-to-Image | Text | Image | DALL-E 3, Midjourney, Stable Diffusion |
| Speech-to-Text | Audio | Text | Whisper, Deepgram |
| Text-to-Speech | Text | Audio | ElevenLabs, OpenAI TTS |
| Video Understanding | Video | Text | Gemini 1.5, GPT-4V (frames) |
| Any-to-Any | Multiple | Multiple | Gemini, GPT-4o |
| Model | Vision | Audio In | Audio Out | Video | Cost |
|---|
| GPT-4o | Excellent | Good | Good | Frames | $$$$ |
| Gemini 1.5 Pro | Excellent | Good | No | Native | $$$ |
| Claude 3 Opus | Excellent | No | No | No | $$$ |
| Llama 3.2 Vision | Good | No | No | No | Free |
| Use Case | Input | Output | Complexity |
|---|
| Image captioning | Image | Description | Low |
| Visual Q&A | Image + Question | Answer | Medium |
| Document OCR | Document image | Structured text | Medium |
| Object detection | Image | Bounding boxes | Medium |
| Visual search | Image | Similar items | High |
| Chart understanding | Chart image | Data extraction | High |
| Requirement | Recommended Model | Why |
|---|
| Highest accuracy | GPT-4V | Best reasoning |
| Long documents | Gemini 1.5 | Large context |
| Cost efficiency | Llama Vision | Free, decent quality |
| Real-time | Custom fine-tuned | Optimized latency |
| Stage | Action | Latency |
|---|
| Upload | Receive image | 50-200ms |
| Preprocessing | Resize, compress | 20-50ms |
| Encoding | Convert to base64 or URL | 10ms |
| API call | Send to model | 500-3000ms |
| Post-processing | Parse response | 10ms |
| Total | End-to-end | 590-3270ms |
Diagram
flowchart LR
A[Image Upload] --> B[Validate Format]
B --> C[Resize if Needed]
C --> D[Compress]
D --> E{Size OK?}
E -->|Yes| F[Encode Base64]
E -->|No| G[Tile Image]
G --> F
F --> H[Vision API Call]
H --> I[Parse Response]
I --> J[Return Result]
style A fill:#14b8a6,color:#fff
style H fill:#f59e0b,color:#fff
style J fill:#22c55e,color:#fff
Typescript
import sharp from 'sharp';
interface ImageProcessingOptions {
maxWidth: number;
maxHeight: number;
quality: number;
format: 'jpeg' | 'webp' | 'png';
}
class ImageProcessor {
private defaults: ImageProcessingOptions = {
maxWidth: 2048,
maxHeight: 2048,
quality: 85,
format: 'jpeg'
};
async prepareForVision(
imageBuffer: Buffer,
options: Partial<ImageProcessingOptions> = {}
): Promise<{ base64: string; metadata: any }> {
const opts = { ...this.defaults, ...options };
// Get original metadata
const metadata = await sharp(imageBuffer).metadata();
// Process image
let pipeline = sharp(imageBuffer);
// Resize if too large
if (metadata.width! > opts.maxWidth || metadata.height! > opts.maxHeight) {
pipeline = pipeline.resize(opts.maxWidth, opts.maxHeight, {
fit: 'inside',
withoutEnlargement: true
});
}
// Compress and convert
const processed = await pipeline
.jpeg({ quality: opts.quality })
.toBuffer();
// Convert to base64
const base64 = processed.toString('base64');
return {
base64: `data:image/jpeg;base64,${base64}`,
metadata: {
originalSize: imageBuffer.length,
processedSize: processed.length,
compression: 1 - (processed.length / imageBuffer.length),
dimensions: {
original: { width: metadata.width, height: metadata.height },
processed: await sharp(processed).metadata()
}
}
};
}
async tileForLargeImage(
imageBuffer: Buffer,
tileSize: number = 1024
): Promise<string[]> {
const metadata = await sharp(imageBuffer).metadata();
const tiles: string[] = [];
const cols = Math.ceil(metadata.width! / tileSize);
const rows = Math.ceil(metadata.height! / tileSize);
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
const tile = await sharp(imageBuffer)
.extract({
left: col * tileSize,
top: row * tileSize,
width: Math.min(tileSize, metadata.width! - col * tileSize),
height: Math.min(tileSize, metadata.height! - row * tileSize)
})
.jpeg({ quality: 85 })
.toBuffer();
tiles.push(`data:image/jpeg;base64,${tile.toString('base64')}`);
}
}
return tiles;
}
}
// Usage with OpenAI Vision
async function analyzeImage(imageBuffer: Buffer): Promise<string> {
const processor = new ImageProcessor();
const { base64, metadata } = await processor.prepareForVision(imageBuffer);
console.log(`Compressed image by ${(metadata.compression * 100).toFixed(1)}%`);
const response = await openai.chat.completions.create({
model: 'gpt-4-vision-preview',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Describe this image in detail.' },
{ type: 'image_url', image_url: { url: base64, detail: 'high' } }
]
}
],
max_tokens: 1000
});
return response.choices[0].message.content!;
}
| Technique | Savings | Trade-off |
|---|
| Image compression | 30-50% latency | Quality loss |
| Resolution reduction | 40-60% latency | Detail loss |
| Tiling for large images | Handles any size | More API calls |
| Caching similar images | 90%+ for repeats | Storage cost |
Speech-to-Text
| Model | Accuracy | Languages | Latency | Cost |
|---|
| Whisper Large | 95%+ | 99 | 1x realtime | Free (self-hosted) |
| Deepgram | 94% | 30+ | 0.3x realtime | $$ |
| Google Speech | 93% | 125+ | 0.5x realtime | $$ |
| AssemblyAI | 94% | 20+ | 0.4x realtime | $$ |
Text-to-Speech
| Model | Quality | Latency | Voices | Cost |
|---|
| ElevenLabs | Excellent | 200ms TTFB | 100+ | $$$ |
| OpenAI TTS | Very good | 150ms TTFB | 6 | $$ |
| Azure TTS | Good | 100ms TTFB | 400+ | $$ |
| Coqui (open) | Good | Variable | Custom | Free |
| Component | Purpose | Latency Target |
|---|
| Audio capture | Record input | Real-time |
| VAD (Voice Activity) | Detect speech | Under 50ms |
| Chunking | Segment audio | Under 20ms |
| Transcription | Speech to text | Under 500ms |
| Processing | LLM response | Under 2s |
| Synthesis | Text to speech | Under 300ms TTFB |
| Approach | Latency | Complexity |
|---|
| Full audio then process | 5-10s | Low |
| Chunked processing | 1-2s | Medium |
| Real-time streaming | 200-500ms | High |
| Approach | Method | Use Case |
|---|
| Frame sampling | Extract key frames | Quick understanding |
| Scene detection | Split by scenes | Narrative analysis |
| Full video | Native video input | Detailed analysis |
| Audio extraction | Transcribe audio track | Content search |
| Strategy | Frames | Coverage | Cost |
|---|
| Uniform | 1 per 10s | Low | Cheap |
| Scene-based | 1 per scene | Medium | Medium |
| Motion-based | On movement | High | Variable |
| Dense | 1 per second | Complete | Expensive |
| Stage | Action | Compute |
|---|
| Ingest | Download/stream video | I/O bound |
| Frame extraction | Sample frames | CPU |
| Audio extraction | Separate audio track | CPU |
| Visual analysis | Process frames with vision model | GPU/API |
| Audio analysis | Transcribe audio | GPU/API |
| Fusion | Combine insights | CPU |
| Video Length | Frames (1/10s) | Vision API Cost | Audio Cost | Total |
|---|
| 1 minute | 6 | $0.05 | $0.01 | $0.06 |
| 10 minutes | 60 | $0.50 | $0.10 | $0.60 |
| 1 hour | 360 | $3.00 | $0.60 | $3.60 |
| Component | Modality | Purpose |
|---|
| Text embeddings | Text | Semantic search |
| Image embeddings | Images | Visual similarity |
| Audio transcripts | Audio | Spoken content |
| Fusion layer | All | Combined retrieval |
| Model | Modality | Dimensions | Quality |
|---|
| CLIP | Image + Text | 512-768 | Good |
| ImageBind | 6 modalities | 1024 | Very good |
| SigLIP | Image + Text | 384-1024 | Excellent |
| Query | Retrieves | Example |
|---|
| Text | Images | "sunset over ocean" finds photos |
| Image | Text | Photo finds descriptions |
| Text | Audio | Query finds podcast segments |
| Image | Similar images | Visual search |
| Application | Acceptable Latency | Optimal |
|---|
| Real-time assistant | Under 2s | Under 1s |
| Document processing | Under 10s | Under 5s |
| Video analysis | Minutes | Under 1 min |
| Batch processing | Hours | Throughput focus |
| Strategy | Savings | Implementation |
|---|
| Resolution optimization | 40-60% | Resize before API |
| Model routing | 50-70% | Simple tasks to cheap models |
| Caching | 30-50% | Cache repeated content |
| Batch processing | 20-30% | Aggregate requests |
| Error Type | Cause | Mitigation |
|---|
| Timeout | Large media | Chunking, async |
| Rate limit | High volume | Queuing, backoff |
| Format error | Unsupported media | Validation, conversion |
| Content filter | Flagged content | Pre-screening |
| Component | Technology | Purpose |
|---|
| Image upload | S3 + CDN | Storage |
| Embedding | CLIP/SigLIP | Vectorization |
| Index | Pinecone/Qdrant | Similarity search |
| Reranking | Vision LLM | Quality filtering |
| Component | Technology | Purpose |
|---|
| Wake word | Local model | Activation |
| STT | Whisper/Deepgram | Transcription |
| LLM | GPT-4o | Understanding |
| TTS | ElevenLabs | Response |
| Component | Technology | Purpose |
|---|
| OCR | GPT-4V/Gemini | Text extraction |
| Layout analysis | Vision model | Structure |
| Entity extraction | LLM | Key information |
| Embedding | Text + visual | Search |
- 1Choose modality-appropriate models - GPT-4V for complex reasoning, Whisper for transcription, specialized models for specialized tasks.
- 2Optimize media before processing - Compression and resolution reduction dramatically reduce cost and latency.
- 3Video is expensive - Frame sampling strategies can reduce costs by 90% with minimal quality loss.
- 4Multimodal RAG is powerful - Cross-modal search enables use cases impossible with text alone.
- 5Latency compounds - Each modality adds latency. Design pipelines to parallelize where possible.
- 6Start with single modality - Master one modality before combining. Complexity increases non-linearly.
Multimodal AI is no longer experimental. The models are capable, the APIs are stable, and the use cases are proven. The question is not whether to go multimodal, but how.