Skip to content

Java: Code example for Generating video with Nova Reel / Bedrock #7360

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 30, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .doc_gen/metadata/bedrock-runtime_metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1648,3 +1648,20 @@ bedrock-runtime_Scenario_InvokeModels:
- php.example_code.bedrock-runtime.basics.scenario
services:
bedrock-runtime: {InvokeModel, InvokeModelWithResponseStream}

bedrock-runtime_Scenario_GenerateVideos_NovaReel:
title: Generate videos from text prompts using &BR; and Nova-Reel
title_abbrev: "Generate videos from text prompts using &BR;"
synopsis: a Spring Boot app that generates videos from text prompts using &BR; and the Nova-Reel model.
category: Scenarios
languages:
Java:
versions:
- sdk_version: 2
github: javav2/example_code/bedrock-runtime
excerpts:
- description: Generate videos from text prompts using &BR; and Nova-Reel.
snippet_tags:
- bedrock-runtime.java2.NovaReel.VideoGeneration
services:
bedrock-runtime: {StartAsyncInvoke, GetAsyncInvoke}
110 changes: 110 additions & 0 deletions javav2/usecases/video_generation_bedrock_nova_reel/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# NovaReel Video Generation Service

This is a Spring Boot application that provides a REST API to generate videos from text prompts using Amazon Bedrock and the Nova-Reel model.

## Overview

The application enables asynchronous video generation using AWS Bedrock's `amazon.nova-reel-v1:0` model and stores the generated videos in an S3 bucket.

It consists of:
- A REST controller for handling API requests
- A service class to interact with Amazon Bedrock
- A response model for encapsulating result data

## Project Structure
![](images/structure.png)
- **NovaReelDemo.java** Main class to bootstrap the Spring Boot app
- **GenerateVideoResponse.java** Response DTO with fields: executionArn, s3Bucket, status
- **VideoGenerationService.java** Service for interacting with Amazon Bedrock
- **VideoGeneratorController.java** REST controller exposing /video endpoints

## Functionality

### 1. Generate Video
**Endpoint:** POST /video/generate
**Query Param:** prompt (string)
**Description:**
- Takes a text prompt
- Sends an async request to `amazon.nova-reel-v1:0` using Bedrock
- The generated video will be stored in the specified S3 bucket in 3-5 mins
- Returns the executionArn

### 2. Check Status
**Endpoint:** POST /video/check
**Query Param:** invocationArn (string)
**Description:**
- Checks the generation status of a video using invocationArn
- Returns the current status

## Configuration

### Prerequisites

- AWS account with access to Amazon Bedrock
- AWS credentials configured via named profile (e.g. `~/.aws/credentials`)
- A valid S3 bucket for output (currently hardcoded)

### Modify S3 Bucket

In `VideoGenerationService.java`, update the following line:
`String s3Bucket = "s3://add_your_bucket_here";`
Replace with your own S3 bucket URI where videos should be saved.

### AWS Credentials

By default, credentials are loaded from a named profile using:
`ProfileCredentialsProvider.create()`
Make sure you have the profile set in your `~/.aws/config` or override it as needed.

### IAM Permissions
Because Amazon Bedrock writes a file to an Amazon S3 bucket on your behalf, the AWS role that you use needs permissions configured to allow the appropriate Amazon Bedrock and Amazon S3 actions
The minimum action permissions required to execute this application are:

```
bedrock:InvokeModel
s3:PutObject
bedrock:GetAsyncInvoke
bedrock:ListAsyncInvokes
```


## How to Run

1. Clone the repo
2. Update the S3 bucket in `VideoGenerationService.java`
3. Set up AWS credentials
4. Build and run the Spring Boot application:
`./mvnw spring-boot:run`
5. Use an API client (e.g. Postman or curl) to interact with the endpoints

## Example Requests

### Generate Video
```
curl -X POST "http://localhost:8080/video/generate?prompt=A cat surfing on a pizza in space"
```

### Check Status
```
curl -X POST "http://localhost:8080/video/check?invocationArn=<your-arn-here>"
```
when status is Completed - video generated and stored in S3 bucket

## Dependencies

- Spring Boot Web
- AWS SDK v2 (Bedrock Runtime)
- Jackson / JSON
- Maven or Gradle for build


## Future Improvements

- Make S3 bucket configurable via `application.yml`
- Add status polling endpoint that waits until generation is complete
- Integrate with frontend or S3 browser to retrieve the generated video

## Additional Materials

- [Amazon Bedrock Overview](https://aws.amazon.com/bedrock/)
- [Amazon Nova Reel - AWS AI Service Cards](https://docs.aws.amazon.com/ai/responsible-ai/nova-reel/overview.html)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 37 additions & 0 deletions javav2/usecases/video_generation_bedrock_nova_reel/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.example</groupId>
<artifactId>nova-reel-test</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>

<dependencies>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>bedrockruntime</artifactId>
<version>2.30.35</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.example.novareel;

public class GenerateVideoResponse {

private String executionArn;
private String s3Bucket;
private String status;


public String getExecutionArn() {
return executionArn;
}

public void setExecutionArn(String executionArn) {
this.executionArn = executionArn;
}

public String getS3Bucket() {
return s3Bucket;
}

public void setS3Bucket(String s3Bucket) {
this.s3Bucket = s3Bucket;
}

public String getStatus() {
return status;
}

public void setStatus(String status) {
this.status = status;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.example.novareel;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class NovaReelDemo {

public static void main(String[] args) {

ConfigurableApplicationContext run = new SpringApplicationBuilder(NovaReelDemo.class)
.web(WebApplicationType.SERVLET)
.run(args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.example.novareel;

// snippet-start:[bedrock-runtime.java2.NovaReel.VideoGeneration]
import org.springframework.stereotype.Service;
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
import software.amazon.awssdk.core.document.Document;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.bedrockruntime.BedrockRuntimeAsyncClient;
import software.amazon.awssdk.services.bedrockruntime.model.*;

import java.util.concurrent.CompletableFuture;

@Service
public class VideoGenerationService {

public GenerateVideoResponse generateVideo(String prompt) {

// add S3 bucket you want to store your generated videos
String s3Bucket = "s3://mygeneratedvidoenovatest";


//Create json request as an instance of Document class
Document novaRequest = prepareDocument(prompt);

// Create request
StartAsyncInvokeRequest request = StartAsyncInvokeRequest.builder()
.modelId("amazon.nova-reel-v1:0")
.modelInput(novaRequest)
.outputDataConfig(AsyncInvokeOutputDataConfig.builder()
.s3OutputDataConfig(AsyncInvokeS3OutputDataConfig.builder().s3Uri(s3Bucket).build())
.build())
.build();

try (BedrockRuntimeAsyncClient bedrockClient = getBedrockRuntimeAsyncClient()) {
CompletableFuture<StartAsyncInvokeResponse> startAsyncInvokeResponseCompletableFuture = bedrockClient.startAsyncInvoke(request);

//blocking operation to wait for the AWS API response
StartAsyncInvokeResponse startAsyncInvokeResponse = startAsyncInvokeResponseCompletableFuture.get();
System.out.println("invocation ARN: " + startAsyncInvokeResponse.invocationArn());

GenerateVideoResponse response = new GenerateVideoResponse();
response.setStatus("inProgress");
response.setExecutionArn(startAsyncInvokeResponse.invocationArn());

return response;
} catch (Exception e) {
System.out.println(e);
throw new RuntimeException(e);
}

}

public GenerateVideoResponse checkGenerationStatus(String invocationArn) {
GenerateVideoResponse response = new GenerateVideoResponse();

try (BedrockRuntimeAsyncClient bedrockClient = getBedrockRuntimeAsyncClient()) {
//creating async request to fetch status by invocation Arn
GetAsyncInvokeRequest asyncRequest = GetAsyncInvokeRequest.builder().invocationArn(invocationArn).build();

CompletableFuture<GetAsyncInvokeResponse> asyncInvoke = bedrockClient.getAsyncInvoke(asyncRequest);

//blocking operation to wait for the AWS API response
GetAsyncInvokeResponse asyncInvokeResponse = asyncInvoke.get();
System.out.println("Invocation status =" + asyncInvokeResponse.statusAsString());

response.setExecutionArn(invocationArn);
response.setStatus(asyncInvokeResponse.statusAsString());
return response;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}

}

private static BedrockRuntimeAsyncClient getBedrockRuntimeAsyncClient() {
BedrockRuntimeAsyncClient bedrockClient = BedrockRuntimeAsyncClient.builder()
.region(Region.US_EAST_1)
.credentialsProvider(ProfileCredentialsProvider.create())
.build();
return bedrockClient;
}

private static Document prepareDocument(String prompt) {
Document textToVideoParams = Document.mapBuilder()
.putString("text", prompt)
.build();

Document videoGenerationConfig = Document.mapBuilder()
.putNumber("durationSeconds", 6)
.putNumber("fps", 24)
.putString("dimension", "1280x720")
.build();

Document novaRequest = Document.mapBuilder()
.putString("taskType", "TEXT_VIDEO")
.putDocument("textToVideoParams", textToVideoParams)
.putDocument("videoGenerationConfig", videoGenerationConfig)
.build();
return novaRequest;
}
}
// snippet-end:[bedrock-runtime.java2.NovaReel.VideoGeneration]
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.example.novareel;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/video")
public class VideoGeneratorController {

@Autowired
VideoGenerationService videoGenerationService;

@PostMapping(value = "/generate", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<GenerateVideoResponse> generateVideo(@RequestParam String prompt) {
return ResponseEntity.ok(videoGenerationService.generateVideo(prompt));
}

@PostMapping(value = "/check", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<GenerateVideoResponse> checkStatus(@RequestParam String invocationArn) {
return ResponseEntity.ok(videoGenerationService.checkGenerationStatus(invocationArn));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
spring:
application:
name: nova-reel-demo

Loading