Skip to content

Commit 12fd604

Browse files
committed
init commit for nova reel video generation app example
1 parent 2fb3602 commit 12fd604

File tree

8 files changed

+331
-0
lines changed

8 files changed

+331
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# NovaReel Video Generation Service
2+
3+
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.
4+
5+
## Overview
6+
7+
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.
8+
9+
It consists of:
10+
- A REST controller for handling API requests
11+
- A service class to interact with Amazon Bedrock
12+
- A response model for encapsulating result data
13+
14+
## Project Structure
15+
![](images/structure.png)
16+
- **NovaReelDemo.java** Main class to bootstrap the Spring Boot app
17+
- **GenerateVideoResponse.java** Response DTO with fields: executionArn, s3Bucket, status
18+
- **VideoGenerationService.java** Service for interacting with Amazon Bedrock
19+
- **VideoGeneratorController.java** REST controller exposing /video endpoints
20+
21+
## Functionality
22+
23+
### 1. Generate Video
24+
**Endpoint:** POST /video/generate
25+
**Query Param:** prompt (string)
26+
**Description:**
27+
- Takes a text prompt
28+
- Sends an async request to `amazon.nova-reel-v1:0` using Bedrock
29+
- The generated video will be stored in the specified S3 bucket in 3-5 mins
30+
- Returns the executionArn
31+
32+
### 2. Check Status
33+
**Endpoint:** POST /video/check
34+
**Query Param:** invocationArn (string)
35+
**Description:**
36+
- Checks the generation status of a video using invocationArn
37+
- Returns the current status
38+
39+
## Configuration
40+
41+
### Prerequisites
42+
43+
- AWS account with access to Amazon Bedrock
44+
- AWS credentials configured via named profile (e.g. `~/.aws/credentials`)
45+
- A valid S3 bucket for output (currently hardcoded)
46+
47+
### Modify S3 Bucket
48+
49+
In `VideoGenerationService.java`, update the following line:
50+
`String s3Bucket = "s3://add_your_bucket_here";`
51+
Replace with your own S3 bucket URI where videos should be saved.
52+
53+
### AWS Credentials
54+
55+
By default, credentials are loaded from a named profile using:
56+
`ProfileCredentialsProvider.create()`
57+
Make sure you have the profile set in your `~/.aws/config` or override it as needed.
58+
59+
### IAM Permissions
60+
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
61+
The minimum action permissions required to execute this application are:
62+
63+
```
64+
bedrock:InvokeModel
65+
s3:PutObject
66+
bedrock:GetAsyncInvoke
67+
bedrock:ListAsyncInvokes
68+
```
69+
70+
71+
## How to Run
72+
73+
1. Clone the repo
74+
2. Update the S3 bucket in `VideoGenerationService.java`
75+
3. Set up AWS credentials
76+
4. Build and run the Spring Boot application:
77+
`./mvnw spring-boot:run`
78+
5. Use an API client (e.g. Postman or curl) to interact with the endpoints
79+
80+
## Example Requests
81+
82+
### Generate Video
83+
```
84+
curl -X POST "http://localhost:8080/video/generate?prompt=A cat surfing on a pizza in space"
85+
```
86+
87+
### Check Status
88+
```
89+
curl -X POST "http://localhost:8080/video/check?invocationArn=<your-arn-here>"
90+
```
91+
92+
## Dependencies
93+
94+
- Spring Boot Web
95+
- AWS SDK v2 (Bedrock Runtime)
96+
- Jackson / JSON
97+
- Maven or Gradle for build
98+
99+
100+
## Future Improvements
101+
102+
- Make S3 bucket configurable via `application.yml`
103+
- Add status polling endpoint that waits until generation is complete
104+
- Integrate with frontend or S3 browser to retrieve the generated video
105+
106+
## Additional Materials
107+
108+
- [Amazon Bedrock Overview](https://aws.amazon.com/bedrock/)
109+
- [Amazon Nova Reel - AWS AI Service Cards](https://docs.aws.amazon.com/ai/responsible-ai/nova-reel/overview.html)
Loading
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<parent>
8+
<groupId>org.springframework.boot</groupId>
9+
<artifactId>spring-boot-starter-parent</artifactId>
10+
<version>3.4.1</version>
11+
<relativePath/> <!-- lookup parent from repository -->
12+
</parent>
13+
14+
<groupId>com.example</groupId>
15+
<artifactId>nova-reel-test</artifactId>
16+
<version>1.0-SNAPSHOT</version>
17+
18+
<properties>
19+
<maven.compiler.source>17</maven.compiler.source>
20+
<maven.compiler.target>17</maven.compiler.target>
21+
</properties>
22+
23+
<dependencies>
24+
25+
<dependency>
26+
<groupId>org.springframework.boot</groupId>
27+
<artifactId>spring-boot-starter-web</artifactId>
28+
</dependency>
29+
30+
<dependency>
31+
<groupId>software.amazon.awssdk</groupId>
32+
<artifactId>bedrockruntime</artifactId>
33+
<version>2.30.35</version>
34+
</dependency>
35+
</dependencies>
36+
37+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.example.novareel;
2+
3+
public class GenerateVideoResponse {
4+
5+
private String executionArn;
6+
private String s3Bucket;
7+
private String status;
8+
9+
10+
public String getExecutionArn() {
11+
return executionArn;
12+
}
13+
14+
public void setExecutionArn(String executionArn) {
15+
this.executionArn = executionArn;
16+
}
17+
18+
public String getS3Bucket() {
19+
return s3Bucket;
20+
}
21+
22+
public void setS3Bucket(String s3Bucket) {
23+
this.s3Bucket = s3Bucket;
24+
}
25+
26+
public String getStatus() {
27+
return status;
28+
}
29+
30+
public void setStatus(String status) {
31+
this.status = status;
32+
}
33+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.example.novareel;
2+
3+
import org.springframework.boot.WebApplicationType;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.boot.builder.SpringApplicationBuilder;
6+
import org.springframework.context.ConfigurableApplicationContext;
7+
8+
@SpringBootApplication
9+
public class NovaReelDemo {
10+
11+
public static void main(String[] args) {
12+
13+
ConfigurableApplicationContext run = new SpringApplicationBuilder(NovaReelDemo.class)
14+
.web(WebApplicationType.SERVLET)
15+
.run(args);
16+
}
17+
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package com.example.novareel;
2+
3+
import org.springframework.stereotype.Service;
4+
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
5+
import software.amazon.awssdk.core.document.Document;
6+
import software.amazon.awssdk.regions.Region;
7+
import software.amazon.awssdk.services.bedrockruntime.BedrockRuntimeAsyncClient;
8+
import software.amazon.awssdk.services.bedrockruntime.model.*;
9+
10+
import java.util.concurrent.CompletableFuture;
11+
12+
@Service
13+
public class VideoGenerationService {
14+
15+
public GenerateVideoResponse generateVideo(String prompt) {
16+
17+
// add S3 bucket you want to store your generated videos
18+
String s3Bucket = "s3://mygeneratedvidoenovatest";
19+
20+
21+
//Create json request as an instance of Document class
22+
Document novaRequest = prepareDocument(prompt);
23+
24+
// Create request
25+
StartAsyncInvokeRequest request = StartAsyncInvokeRequest.builder()
26+
.modelId("amazon.nova-reel-v1:0")
27+
.modelInput(novaRequest)
28+
.outputDataConfig(AsyncInvokeOutputDataConfig.builder()
29+
.s3OutputDataConfig(AsyncInvokeS3OutputDataConfig.builder().s3Uri(s3Bucket).build())
30+
.build())
31+
.build();
32+
33+
try (BedrockRuntimeAsyncClient bedrockClient = getBedrockRuntimeAsyncClient()) {
34+
CompletableFuture<StartAsyncInvokeResponse> startAsyncInvokeResponseCompletableFuture = bedrockClient.startAsyncInvoke(request);
35+
36+
//blocking operation to wait for the AWS API response
37+
StartAsyncInvokeResponse startAsyncInvokeResponse = startAsyncInvokeResponseCompletableFuture.get();
38+
System.out.println("invocation ARN: " + startAsyncInvokeResponse.invocationArn());
39+
40+
GenerateVideoResponse response = new GenerateVideoResponse();
41+
response.setStatus("inProgress");
42+
response.setExecutionArn(startAsyncInvokeResponse.invocationArn());
43+
44+
return response;
45+
} catch (Exception e) {
46+
System.out.println(e);
47+
throw new RuntimeException(e);
48+
}
49+
50+
}
51+
52+
public GenerateVideoResponse checkGenerationStatus(String invocationArn) {
53+
GenerateVideoResponse response = new GenerateVideoResponse();
54+
55+
try (BedrockRuntimeAsyncClient bedrockClient = getBedrockRuntimeAsyncClient()) {
56+
//creating async request to fetch status by invocation Arn
57+
GetAsyncInvokeRequest asyncRequest = GetAsyncInvokeRequest.builder().invocationArn(invocationArn).build();
58+
59+
CompletableFuture<GetAsyncInvokeResponse> asyncInvoke = bedrockClient.getAsyncInvoke(asyncRequest);
60+
61+
//blocking operation to wait for the AWS API response
62+
GetAsyncInvokeResponse asyncInvokeResponse = asyncInvoke.get();
63+
System.out.println("Invocation status =" + asyncInvokeResponse.statusAsString());
64+
65+
response.setExecutionArn(invocationArn);
66+
response.setStatus(asyncInvokeResponse.statusAsString());
67+
return response;
68+
} catch (Exception e) {
69+
e.printStackTrace();
70+
throw new RuntimeException(e);
71+
}
72+
73+
}
74+
75+
private static BedrockRuntimeAsyncClient getBedrockRuntimeAsyncClient() {
76+
BedrockRuntimeAsyncClient bedrockClient = BedrockRuntimeAsyncClient.builder()
77+
.region(Region.US_EAST_1)
78+
.credentialsProvider(ProfileCredentialsProvider.create())
79+
.build();
80+
return bedrockClient;
81+
}
82+
83+
private static Document prepareDocument(String prompt) {
84+
Document textToVideoParams = Document.mapBuilder()
85+
.putString("text", prompt)
86+
.build();
87+
88+
Document videoGenerationConfig = Document.mapBuilder()
89+
.putNumber("durationSeconds", 6)
90+
.putNumber("fps", 24)
91+
.putString("dimension", "1280x720")
92+
.build();
93+
94+
Document novaRequest = Document.mapBuilder()
95+
.putString("taskType", "TEXT_VIDEO")
96+
.putDocument("textToVideoParams", textToVideoParams)
97+
.putDocument("videoGenerationConfig", videoGenerationConfig)
98+
.build();
99+
return novaRequest;
100+
}
101+
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.example.novareel;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.http.MediaType;
5+
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.annotation.PostMapping;
7+
import org.springframework.web.bind.annotation.RequestMapping;
8+
import org.springframework.web.bind.annotation.RequestParam;
9+
import org.springframework.web.bind.annotation.RestController;
10+
11+
@RestController
12+
@RequestMapping("/video")
13+
public class VideoGeneratorController {
14+
15+
@Autowired
16+
VideoGenerationService videoGenerationService;
17+
18+
@PostMapping(value = "/generate", produces = MediaType.APPLICATION_JSON_VALUE)
19+
public ResponseEntity<GenerateVideoResponse> generateVideo(@RequestParam String prompt) {
20+
return ResponseEntity.ok(videoGenerationService.generateVideo(prompt));
21+
}
22+
23+
@PostMapping(value = "/check", produces = MediaType.APPLICATION_JSON_VALUE)
24+
public ResponseEntity<GenerateVideoResponse> checkStatus(@RequestParam String invocationArn) {
25+
return ResponseEntity.ok(videoGenerationService.checkGenerationStatus(invocationArn));
26+
}
27+
28+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
spring:
2+
application:
3+
name: nova-reel-demo
4+

0 commit comments

Comments
 (0)