Skip to content

kousen/VeoJava

Repository files navigation

Veo Java - Google Gemini Veo 3 Video Generator Java Client

License: MIT Java Spring Boot Quality Gate Status Coverage Build and Analyze

This Spring Boot application demonstrates multiple approaches to integrate with Google's Gemini Veo 3 video generation API from Java. The implementation is based on the REST API documented at https://ai.google.dev/gemini-api/docs/video (note that the official examples only show Python, JavaScript, and Go, but this project demonstrates Java integration patterns).

⚠️ Important: This is a demonstration project showing different Java polling strategies for long-running operations. Each video generation costs ~$3.20 with the fast preview model and requires Google API access approval.

Features

  • Multiple Client Implementations:

    • Spring RestClient
    • Java HttpClient (standalone)
    • Reactive WebClient
  • Multiple Polling Strategies:

    • SelfScheduling-based polling (dynamic intervals)
    • FixedRate-based polling (fixed intervals)
    • VirtualThread-based polling (Java 21+)
    • Reactive Flux-based polling (WebClient compatibility issue - see notes)
  • REST API Endpoints for testing all approaches

  • Configuration via application.properties

  • Video File Saving with Base64 decoding

Prerequisites

  1. Java 24 or later (with preview features for primitive patterns)
  2. Gradle (wrapper included)
  3. Gemini API Key with Veo 3 Access — Set the GOOGLEAI_API_KEY or GEMINI_API_KEY environment variable
    • Note: Veo 3 is in controlled access and may require approval from Google

Getting Started

1. Set up your API key

export GOOGLEAI_API_KEY="your-api-key-here"
# OR
export GEMINI_API_KEY="your-api-key-here"

2. Build the project

./gradlew build

3. Run the application

Choose one of these approaches:

# Spring Boot application (full context)
./gradlew bootRun

# Lightweight demo (application plugin)
./gradlew run

# Or from IDE after setting Java 24
# Run VeoVideoDemo.main() directly

4. Test the endpoints

The application starts on http://localhost:8080

API Endpoints

Generate Video (different approaches)

  • POST /api/video/generate/rest-client
  • POST /api/video/generate/http-client
  • POST /api/video/generate/self-scheduling
  • POST /api/video/generate/fixed-rate
  • POST /api/video/generate/virtual-thread
  • POST /api/video/generate/reactive

Request body:

{
  "prompt": "A cat playing with a ball of yarn in a sunny garden"
}

Utility Endpoints

  • GET /api/video/strategies - List available strategies
  • GET /api/video/health - Health check

Example Usage

Using cURL

curl -X POST http://localhost:8080/api/video/generate/rest-client \
  -H "Content-Type: application/json" \
  -d '{"prompt": "A beautiful sunset over mountains"}'

Interactive Demo

⚠️ Cost Warning: Each video costs ~$3.20 (8 seconds × $0.40/second with fast preview model)

Run the interactive demo:

# Recommended: Use Gradle (handles Java 24 toolchain automatically)
./gradlew run

# Alternative: Direct execution (requires Java 24 with preview features)
# java --enable-preview -cp "build/classes/java/main:$(./gradlew -q printClasspath)" com.kousenit.veojava.VeoVideoDemo

The demo will present an interactive menu where you can:

  • Choose which approach to test (options 1-6)
  • Enter custom prompts or use the default
  • See cost warnings before generating videos
  • Compare different implementations safely

Available options in demo:

  1. HttpClient (pure Java, no Spring)
  2. RestClient (Spring's modern HTTP client)
  3. SelfScheduling polling strategy
  4. FixedRate polling strategy
  5. Reactive polling strategy ⚠️ (known WebClient compatibility issue)
  6. VirtualThread polling strategy

Configuration

Edit src/main/resources/application.properties:

# API Configuration - checks GOOGLEAI_API_KEY first, then GEMINI_API_KEY
gemini.api.key=${GOOGLEAI_API_KEY:${GEMINI_API_KEY}}
veo.api.model=veo-3.0-fast-generate-preview

# Polling Configuration
veo.polling.interval-seconds=5
veo.polling.max-timeout-minutes=10

# Output Configuration
veo.output.directory=./videos

# Async Configuration - video generation takes 2-4 minutes
spring.mvc.async.request-timeout=600000

Implementation Details

Client Approaches

  1. RestClient — Uses Spring's RestClient with autoconfigured Jackson
  2. HttpClient — Uses Java 11+ HttpClient with explicit ObjectMapper
  3. ReactiveClient — Uses WebClient with Mono/Flux patterns

Polling Strategies

  1. SelfScheduling — Reschedules after each check completes (dynamic timing)
  2. FixedRate — Uses ScheduledExecutorService for fixed periodic checks
  3. VirtualThread — Uses virtual threads for lightweight blocking operations (recommended)
  4. Reactive — Uses Flux.interval with clean polling patterns (WebClient compatibility issue)

Video Generation Process

  1. Submit video generation request → Get operation ID
  2. Poll operation status every 5 seconds → Wait for done: true
  3. Extract download URL from response → Get file URI with redirect
  4. Download video file → Follow 302 redirects to actual content
  5. Save to local file system → Write binary data to MP4 file

Key Discovery: Veo 3 returns download URLs instead of base64-encoded data, requiring redirect handling for proper file retrieval.

Important Notes

  • Paid Feature: Veo 3 fast preview costs $0.40/second (~$3.20 for 8-second videos)
  • 8-second videos: Current limitation of the API
  • 720p @ 24 fps: Fixed resolution and frame rate
  • Redirect handling: All HTTP clients must follow 302 redirects for video downloads
  • Buffer limits: WebClient requires 2MB+ buffer for video files (default 256KB insufficient)
  • Content filtering: Audio may be blocked while video succeeds
  • Controlled access: Veo 3 requires special API access approval
  • English prompts: Only English language supported
  • Async timeout: REST endpoints require 10-minute timeout due to 2-4 minute generation time
  • ⚠️ WebClient Compatibility: The reactive approach (option 5) has a known compatibility issue with Google's Veo 3 API where identical requests work with HttpClient but fail with 400 Bad Request using WebClient/Reactor Netty. This appears to be a low-level protocol incompatibility. Use VirtualThread approach (option 6) for best reactive-style experience.

Project Structure

src/main/java/com/kousenit/veojava/
├── client/           # HTTP client implementations
├── config/           # Spring configuration
├── controller/       # REST endpoints
├── model/            # Data models (records)
├── service/          # Business logic and polling strategies
└── VeoVideoDemo.java # Standalone demo

Testing

Run tests:

./gradlew test

Note: Integration tests are disabled by default (using @Disabled) to prevent accidental API costs. Each test video costs ~$6 and takes several minutes to generate.

Test Coverage: The project includes comprehensive unit tests covering:

  • Service layer with mocked clients using @MockitoBean (Spring Boot 3.4+)
  • REST controller endpoints with proper async testing patterns
  • All polling strategies with business logic validation
  • Input validation with Bean Validation (@Valid, @NotBlank)
  • Resource cleanup patterns with @PreDestroy methods

Build and Run

Build the project:

./gradlew build

Run all checks including tests:

./gradlew check

Create a distribution:

./gradlew bootJar
java -jar build/libs/VeoJava-0.0.1-SNAPSHOT.jar

Architecture Highlights

This project demonstrates several key Java/Spring patterns:

  • Multiple HTTP Client Approaches: Compare Spring RestClient, Java HttpClient, and WebClient
  • Async Patterns: SelfScheduling, FixedRate, VirtualThread, and Reactive streams
  • Polling Strategy Analysis: Comprehensive comparison of non-busy-waiting approaches
  • Record-Based Data Models: All DTOs in a single VeoJavaRecords class for easy static imports
  • Modern Java Features: Sealed interfaces, pattern matching, virtual threads, text blocks, primitive patterns with guards (Java 24 preview), exception pattern matching
  • Configuration Properties: Type-safe configuration with @ConfigurationProperties and proper Spring Boot 3.4+ patterns
  • Polling Strategies: Different approaches to handle long-running operations with proper resource cleanup
  • Error Handling: Comprehensive error handling across sync and async flows
  • Resource Management: Proper @PreDestroy cleanup for ScheduledExecutorService instances to prevent memory leaks
  • Input Validation: Bean Validation with @Valid and @NotBlank annotations
  • Testing Patterns: Modern Spring Boot testing with @MockitoBean, async controller testing, and cost-protection measures

Modern Java Features Showcase

This project demonstrates cutting-edge Java 24 features:

  • MODERN_JAVA_FEATURES.md - Comprehensive documentation of Java 24 preview features and modern patterns
  • Primitive Patterns with Guards: Type-safe pattern matching on primitive types
  • Text Blocks: Multi-line strings throughout the application
  • Exception Pattern Matching: Clean error handling with switch expressions
  • Enhanced Switch Expressions: Multiple case values and arrow syntax

YouTube Tutorial

This project includes comprehensive educational content for Java developers:

The tutorial covers the journey from naive busy-waiting to enterprise-grade async patterns, perfect for developers learning modern Java concurrency patterns.

Additional Documentation

Educational Value

This project serves multiple purposes:

  1. Production Example: Real-world integration with Google's Veo 3 API including proper error handling, timeouts, and redirect management
  2. Learning Resource: Comprehensive comparison of 5 different polling strategies from naive blocking to advanced async patterns
  3. Modern Java Showcase: Demonstrates records, sealed interfaces, virtual threads, primitive patterns with guards (Java 24 preview), reactive streams, and other contemporary features
  4. Performance Analysis: Includes detailed metrics and recommendations for different concurrency approaches

Contributing

This is a demonstration project showing different Java approaches to REST API integration with async polling patterns. The implementation includes important discoveries about Google's Veo 3 API behavior, particularly around redirect handling and URL-based video delivery. Feel free to explore and adapt the patterns for your own use cases.

The educational materials (script.md, comparison tables, diagrams) are designed to help other developers understand the trade-offs between different async programming approaches in Java.