Gemini Omni Flash로 비디오 생성·편집하기
Gemini Omni Flash로 비디오 생성·편집하기
Gemini Omni Flash(gemini-omni-1.1-flash)는 고속 비디오 생성, 편집, 시네마틱 제어를 위해 설계된 고성능 멀티모달 모델이에요. Gemini Omni는 이전 비디오 모델과 구별되는 다음 핵심 능력 위에 구축됐어요.
- 네이티브 멀티모달: 텍스트, 이미지, 오디오, 비디오를 동시에 처리해 더 응집력 있고 일관되며 제어 가능한 출력을 제공해요.
- 대화형 편집(Conversational editing): Interactions API로 가능해진 기능으로, 자연어 대화를 통해 비디오를 반복적으로 정제·편집할 수 있어요. 바꾸고 싶은 것을 설명하면 모델이 유지하고 싶은 부분은 보존하면서 편집을 적용해요.
- 세계 지식(World knowledge): Gemini Omni는 물리 이해와 Gemini의 역사·과학·문화적 맥락 지식을 결합해 포토리얼리즘에서 의미 있는 스토리텔링까지의 간극을 메워요.
출처: 문서
본문
텍스트-투-비디오 생성 (Text to video generation)
텍스트 프롬프트에서 비디오를 생성해요. 모델은 텍스트 설명에 기반해 오디오가 포함된 비디오를 생성해요. 최상의 결과를 위해 장면 설명, 카메라 움직임, 조명, 분위기 같은 세부 사항을 프롬프트에 작성하세요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input="A marble rolling fast on a chain reaction style track, continuous smooth shot."
)
with open("marble.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: 'A marble rolling fast on a chain reaction style track, continuous smooth shot.',
});
if (interaction.output_video?.data) {
fs.writeFileSync('marble.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(
InteractionsInput.of(
"A marble rolling fast on a chain reaction style track, continuous smooth shot."))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("marble.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(
"A marble rolling fast on a chain reaction style track, continuous smooth shot.",
),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("marble.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": "A marble rolling fast on a chain reaction style track, continuous smooth shot."
}'
REST 응답 스키마
편의 필드인 interaction.output_video는 SDK 전용이에요. REST API를 직접 사용할 때는 steps 배열에서 비디오 출력을 가져오세요.
원시 REST JSON 구조:
{
"steps": [
{ "type": "user_input", "content": [{"type": "text", "text": "..."}] },
{ "type": "thought", "content": [{"text": "...", "type": "thought"}] },
{
"type": "model_output",
"content": [
{
"type": "video",
"mime_type": "video/mp4",
"data": "AAAAIGZ0eXBpc29t..." // Base64 encoded video data
}
]
}
],
"id": "v1_...",
"status": "completed",
"model": "gemini-omni-1.1-flash",
"object": "interaction"
}
종횡비 제어
aspect_ratio를 "9:16"으로 설정하면 세로 비디오를 만들 수 있어요. 가로(16:9)가 기본값이에요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input="A futuristic city with neon lights and flying cars, cyberpunk style",
response_format={
"type": "video", # optional
"aspect_ratio": "9:16" # Supported values: "9:16", "16:9"
}
)
with open("example.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: 'A futuristic city with neon lights and flying cars, cyberpunk style',
response_format: {
type: 'video', // optional
aspect_ratio: '9:16' // Supported values: '9:16', '16:9'
},
});
if (interaction.output_video?.data) {
fs.writeFileSync('example.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ResponseFormat;
import com.google.genai.gaos.models.interactions.VideoResponseFormat;
import com.google.genai.gaos.models.interactions.VideoResponseFormatAspectRatio;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
Client client = new Client();
VideoResponseFormat videoFormat =
VideoResponseFormat.builder()
.aspectRatio(VideoResponseFormatAspectRatio.of("9:16"))
.build();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(
InteractionsInput.of(
"A futuristic city with neon lights and flying cars, cyberpunk style"))
.responseFormat(CreateModelInteractionResponseFormat.of(ResponseFormat.of(videoFormat)))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("example.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
videoFormat := interactions.VideoResponseFormat{
AspectRatio: interactions.VideoResponseFormatAspectRatioNineHundredAndSixteen.ToPointer(),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(
"A futuristic city with neon lights and flying cars, cyberpunk style",
),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(videoFormat),
)),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("example.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": "A futuristic city with neon lights and flying cars, cyberpunk style",
"response_format": {
"type": "video",
"aspect_ratio": "9:16"
}
}'
출력 해상도
response_format의 resolution 파라미터로 생성된 비디오의 출력 해상도를 제어해요. 기본 해상도는 720p예요.
| 값 | 설명 |
|---|---|
360p |
360p 출력 해상도 |
720p |
720p 출력 해상도(기본) |
1080p |
1080p 출력(업스케일) |
4k |
4K 출력(업스케일) |
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input="A drone shot of a mountain landscape at sunrise.",
response_format={
"type": "video",
"resolution": "1080p",
},
)
with open("hires.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: 'A drone shot of a mountain landscape at sunrise.',
response_format: {
type: 'video',
resolution: '1080p',
},
});
if (interaction.output_video?.data) {
fs.writeFileSync('hires.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.Resolution;
import com.google.genai.gaos.models.interactions.ResponseFormat;
import com.google.genai.gaos.models.interactions.VideoResponseFormat;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
Client client = new Client();
VideoResponseFormat videoFormat =
VideoResponseFormat.builder()
.resolution(Resolution.of("1080p"))
.build();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.of("A drone shot of a mountain landscape at sunrise."))
.responseFormat(CreateModelInteractionResponseFormat.of(ResponseFormat.of(videoFormat)))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("hires.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
videoFormat := interactions.VideoResponseFormat{
Resolution: interactions.ResolutionOneThousandAndEightyp.ToPointer(),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput("A drone shot of a mountain landscape at sunrise."),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(videoFormat),
)),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("hires.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": "A drone shot of a mountain landscape at sunrise.",
"response_format": {
"type": "video",
"resolution": "1080p"
}
}'
브라우저에서 비디오 태그를 지원하지 않습니다.
이미지-투-비디오 생성 (Image to video generation)
텍스트 프롬프트와 함께 참조 이미지를 제공할 수 있어요. 프롬프트에 따라 모델이 이미지를 어떻게 사용할지 결정해요. 이는 제품 사진, 일러스트레이션, 사진에 생명을 불어넣는 데 유용해요.
다음 예시는 물 밖으로 뛰어오르는 물고기 그림의 참조 이미지를 사용하는 방법을 보여줘요.
[이미지: /static/gemini-api/docs/images/fish-jumping-inputimage.png]
다음 프롬프트와 함께:
turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video
그림의 사실적인 비디오를 생성하려고 해요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "image", "data": base64_image, "mime_type": "image/jpeg"},
{"type": "text", "text": "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video"}
],
)
with open("clownfish.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'image', data: base64Image, mime_type: 'image/jpeg' },
{ type: 'text', text: 'turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video' }
]
});
if (interaction.output_video?.data) {
fs.writeFileSync('clownfish.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.ImageContentMimeType;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
byte[] imageBytes = Files.readAllBytes(Paths.get("drawing.jpg"));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
Content imageContent =
ImageContent.builder()
.data(base64Image)
.mimeType(ImageContentMimeType.IMAGE_JPEG)
.build();
Content textContent =
TextContent.builder()
.text(
"turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video")
.build();
List<Content> contents = Arrays.asList(imageContent, textContent);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("clownfish.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
imageBytes, err := os.ReadFile("drawing.jpg")
if err != nil {
log.Fatal(err)
}
base64Image := base64.StdEncoding.EncodeToString(imageBytes)
contents := []interactions.Content{
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(base64Image),
MimeType: interactions.ImageContentMimeTypeImageJpeg.ToPointer(),
}),
interactions.NewContent(interactions.TextContent{
Text: "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("clownfish.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": [
{"type": "image", "data": "'"$BASE64_IMAGE"'", "mime_type": "image/jpeg"},
{"type": "text", "text": "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video"}
]
}'
참고: 이미지-투-비디오의 최상의 결과를 위해 고해상도 이미지를 사용하고 구체적인 움직임 설명을 제공하세요. "움직이게 해줘" 같은 모호한 프롬프트는 카메라 움직임, 피사체 움직임, 환경 효과의 상세한 설명보다 덜 설득력 있는 결과를 만들어요.
첫·마지막 프레임 보간
Gemini Omni Flash는 비디오 보간을 지원해 시작 이미지(첫 프레임)와 끝 이미지(마지막 프레임) 사이를 매끄럽게 전환하는 비디오를 생성할 수 있게 해요.
input 목록에 두 개의 이미지를 제공하고 프롬프트에서 원하는 전환을 설명하세요. 모델이 첫 프레임에서 마지막 프레임까지 장면을 애니메이션화해요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "image", "data": first_frame_b64, "mime_type": "image/jpeg"},
{"type": "image", "data": last_frame_b64, "mime_type": "image/jpeg"},
{"type": "text", "text": "A smooth cinematic transition from a lush green forest at sunrise to a snowy forest under a starry night sky."}
],
)
with open("interpolation.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'image', data: firstFrameB64, mime_type: 'image/jpeg' },
{ type: 'image', data: lastFrameB64, mime_type: 'image/jpeg' },
{ type: 'text', text: 'A smooth cinematic transition from a lush green forest at sunrise to a snowy forest under a starry night sky.' }
]
});
if (interaction.output_video?.data) {
fs.writeFileSync('interpolation.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.ImageContentMimeType;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
String firstFrameB64 =
Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("first_frame.jpg")));
String lastFrameB64 =
Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("last_frame.jpg")));
Content firstFrame =
ImageContent.builder()
.data(firstFrameB64)
.mimeType(ImageContentMimeType.IMAGE_JPEG)
.build();
Content lastFrame =
ImageContent.builder()
.data(lastFrameB64)
.mimeType(ImageContentMimeType.IMAGE_JPEG)
.build();
Content prompt =
TextContent.builder()
.text(
"A smooth cinematic transition from a lush green forest at sunrise to a snowy forest under a starry night sky.")
.build();
List<Content> contents = Arrays.asList(firstFrame, lastFrame, prompt);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("interpolation.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
firstBytes, err := os.ReadFile("first_frame.jpg")
if err != nil {
log.Fatal(err)
}
lastBytes, err := os.ReadFile("last_frame.jpg")
if err != nil {
log.Fatal(err)
}
firstFrameB64 := base64.StdEncoding.EncodeToString(firstBytes)
lastFrameB64 := base64.StdEncoding.EncodeToString(lastBytes)
contents := []interactions.Content{
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(firstFrameB64),
MimeType: interactions.ImageContentMimeTypeImageJpeg.ToPointer(),
}),
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(lastFrameB64),
MimeType: interactions.ImageContentMimeTypeImageJpeg.ToPointer(),
}),
interactions.NewContent(interactions.TextContent{
Text: "A smooth cinematic transition from a lush green forest at sunrise to a snowy forest under a starry night sky.",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("interpolation.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": [
{"type": "image", "data": "'"$FIRST_FRAME_B64"'", "mime_type": "image/jpeg"},
{"type": "image", "data": "'"$LAST_FRAME_B64"'", "mime_type": "image/jpeg"},
{"type": "text", "text": "A smooth cinematic transition from a lush green forest at sunrise to a snowy forest under a starry night sky."}
]
}'
브라우저에서 비디오 태그를 지원하지 않습니다.
피사체 참조 (Subject reference)
참조 이미지로 제공된 특정 피사체를 포함한 비디오를 생성할 수 있어요. 예를 들어 다음 코드는 고양이와 실 공 2장의 이미지를 제공해 고양이가 실을 가지고 노는 비디오를 생성하는 방법을 보여줘요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "image", "data": cat_b64, "mime_type": "image/png"},
{"type": "image", "data": yarn_b64, "mime_type": "image/png"},
{"type": "text", "text": "A cat playfully batting at a ball of yarn."}
],
)
with open("cat.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'image', data: catData, mime_type: 'image/png' },
{ type: 'image', data: yarnData, mime_type: 'image/png' },
{ type: 'text', text: 'A cat playfully batting at a ball of yarn.' }
]
});
if (interaction.output_video?.data) {
fs.writeFileSync('cat.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.ImageContentMimeType;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
String catB64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("cat.png")));
String yarnB64 = Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get("yarn.png")));
Content catImage =
ImageContent.builder()
.data(catB64)
.mimeType(ImageContentMimeType.IMAGE_PNG)
.build();
Content yarnImage =
ImageContent.builder()
.data(yarnB64)
.mimeType(ImageContentMimeType.IMAGE_PNG)
.build();
Content textContent =
TextContent.builder()
.text("A cat playfully batting at a ball of yarn.")
.build();
List<Content> contents = Arrays.asList(catImage, yarnImage, textContent);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("cat.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
catBytes, err := os.ReadFile("cat.png")
if err != nil {
log.Fatal(err)
}
yarnBytes, err := os.ReadFile("yarn.png")
if err != nil {
log.Fatal(err)
}
catB64 := base64.StdEncoding.EncodeToString(catBytes)
yarnB64 := base64.StdEncoding.EncodeToString(yarnBytes)
contents := []interactions.Content{
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(catB64),
MimeType: interactions.ImageContentMimeTypeImagePng.ToPointer(),
}),
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(yarnB64),
MimeType: interactions.ImageContentMimeTypeImagePng.ToPointer(),
}),
interactions.NewContent(interactions.TextContent{
Text: "A cat playfully batting at a ball of yarn.",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("cat.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": [
{"type": "image", "data": "'"$CAT_B64"'", "mime_type": "image/png"},
{"type": "image", "data": "'"$YARN_B64"'", "mime_type": "image/png"},
{"type": "text", "text": "A cat playfully batting at a ball of yarn."}
]
}'
Tasks 파라미터
video_config의 task 파라미터를 사용해 의도한 동작을 명시적으로 지정할 수 있어요. 예를 들어 이미지에서 비디오를 생성하려면 파라미터를 image_to_video로 설정하면 돼요. 설정하지 않으면 모델이 프롬프트에서 원하는 바를 추론해요.
팁: task 필드는 몇 가지 제약을 추가하므로, 프롬프팅을 주로 사용하고 프롬프팅이 작동하지 않을 때만 task 파라미터로 모델이 어떤 모드를 사용해야 하는지 돕는 것을 권장해요.
허용되는 값은 다음과 같아요.
text_to_videoimage_to_videoreference_to_videoeditextend
다음 예시는 앞서 보여준 이미지-투-비디오 예시에 이를 설정하는 방법을 보여줘요.
Python
import base64
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "image", "data": base64_image, "mime_type": "image/jpeg"},
{"type": "text", "text": "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video"}
],
generation_config={
"video_config": {
"task": "image_to_video",
}
},
)
with open("example.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from "@google/genai";
import * as fs from 'fs';
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'image', data: base64Image, mime_type: 'image/jpeg' },
{ type: 'text', text: 'turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video' }
],
generationConfig: {
videoConfig: {
task: 'image_to_video',
}
}
});
if (interaction.output_video?.data) {
fs.writeFileSync('example.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.GenerationConfig;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.ImageContentMimeType;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.Task;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.interactions.VideoConfig;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
byte[] imageBytes = Files.readAllBytes(Paths.get("drawing.jpg"));
String base64Image = Base64.getEncoder().encodeToString(imageBytes);
Content imageContent =
ImageContent.builder()
.data(base64Image)
.mimeType(ImageContentMimeType.IMAGE_JPEG)
.build();
Content textContent =
TextContent.builder()
.text(
"turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video")
.build();
List<Content> contents = Arrays.asList(imageContent, textContent);
GenerationConfig generationConfig =
GenerationConfig.builder()
.videoConfig(VideoConfig.builder().task(Task.IMAGE_TO_VIDEO).build())
.build();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.generationConfig(generationConfig)
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("example.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
imageBytes, err := os.ReadFile("drawing.jpg")
if err != nil {
log.Fatal(err)
}
base64Image := base64.StdEncoding.EncodeToString(imageBytes)
contents := []interactions.Content{
interactions.NewContent(interactions.ImageContent{
Data: genai.Ptr(base64Image),
MimeType: interactions.ImageContentMimeTypeImageJpeg.ToPointer(),
}),
interactions.NewContent(interactions.TextContent{
Text: "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video",
}),
}
generationConfig := &interactions.GenerationConfig{
VideoConfig: &interactions.VideoConfig{
Task: interactions.TaskImageToVideo.ToPointer(),
},
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
GenerationConfig: generationConfig,
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("example.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": [
{
"type": "image",
"data": "'"$BASE64_IMAGE"'",
"mime_type": "image/jpeg"
},
{
"type": "text",
"text": "turn this into realistic footage, using the drawing only as a guide for movement, do not show the drawing in the final video"
}
],
"generation_config": {
"video_config": {
"task": "image_to_video"
}
}
}'
상태가 있는 비디오 편집 (Stateful video editing)
비디오를 생성하고 후속 프롬프트로 반복 편집해요. 각 턴은 이전 결과 위에 구축돼요. 모델은 비디오 컨텍스트를 기억해 언급하지 않은 요소는 보존하면서 변경사항을 적용해요. previous_interaction_id를 사용해 이전 비디오를 다시 업로드하지 않고 대화 기록과 생성된 비디오 상태를 추적해요.
참고: 비디오 편집 제한의 자세한 목록은 Limitations 참고.
다음 예시는 첫 비디오를 생성한 다음 편집하는 방법을 보여줘요.
Python
import base64
from google import genai
client = genai.Client()
# Turn 1: Generate initial video
res1 = client.interactions.create(model="gemini-omni-1.1-flash", input="A woman playing violin outdoors.")
# Turn 2: Edit the previous video
res2 = client.interactions.create(
model="gemini-omni-1.1-flash",
previous_interaction_id=res1.id,
input="Make the violin invisible."
)
with open("example.mp4", "wb") as f:
f.write(base64.b64decode(res2.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
// Turn 1: Generate initial video
const res1 = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: 'A woman playing violin outdoors.',
});
// Turn 2: Edit the previous video
const res2 = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
previous_interaction_id: res1.id,
input: 'Make the violin invisible.',
});
if (res2.output_video?.data) {
fs.writeFileSync('example.mp4', Buffer.from(res2.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
Client client = new Client();
// Turn 1: Generate initial video
CreateModelInteraction turn1Params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.of("A woman playing violin outdoors."))
.build();
Interaction res1 =
client.interactions.create(CreateInteractionRequestBody.of(turn1Params)).interaction().get();
// Turn 2: Edit the previous video
CreateModelInteraction turn2Params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.previousInteractionId(res1.id().get())
.input(InteractionsInput.of("Make the violin invisible."))
.build();
Interaction res2 =
client.interactions.create(CreateInteractionRequestBody.of(turn2Params)).interaction().get();
if (res2.outputVideo().isPresent() && res2.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(res2.outputVideo().get().data().get());
Files.write(Paths.get("example.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Turn 1: Generate initial video
res1, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput("A woman playing violin outdoors."),
}),
})
if err != nil {
log.Fatal(err)
}
// Turn 2: Edit the previous video
res2, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
PreviousInteractionID: res1.Interaction.ID,
Input: interactions.NewInteractionsInput("Make the violin invisible."),
}),
})
if err != nil {
log.Fatal(err)
}
if res2.Interaction.OutputVideo != nil && res2.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res2.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("example.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"previous_interaction_id": "'"$PREVIOUS_ID"'",
"input": "Make the violin invisible."
}'
초기 비디오의 예시:
편집된 비디오의 예시:
대화의 각 턴은 새 비디오를 생성해요. 모델은 이전 턴의 컨텍스트를 이해하므로, 조명 조정, 배경 교체처럼 전체 장면을 다시 설명하지 않고도 증분 변경을 할 수 있어요.
내 비디오 편집하기
Files API로 비디오를 업로드해 Gemini Omni Flash로 편집할 수 있어요.
참고: 업로드한 비디오 편집은 모든 지역에서 사용할 수 없어요. 자세한 내용은 Limitations 섹션 참고.
다음 예시는 다음 원본 비디오를 편집하는 방법을 보여줘요.
Python
import time
import base64
from google import genai
client = genai.Client()
# Upload video using the file API
video_file = client.files.upload(file="Video.mp4")
while video_file.state == "PROCESSING":
print('Waiting for video to be processed.')
time.sleep(10)
video_file = client.files.get(name=video_file.name)
if video_file.state == "FAILED":
raise ValueError(video_file.state)
print(f'Video processing complete: ' + video_file.uri)
# Edit your video
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "video", "uri": video_file.uri},
{"type": "text", "text": "When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material"}
],
)
with open("example.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
// Upload video using the file API
let videoFile = await ai.files.upload({
file: 'Video.mp4',
});
while (videoFile.state === 'PROCESSING') {
console.log('Waiting for video to be processed.');
await new Promise(r => setTimeout(r, 10000));
videoFile = await ai.files.get({ name: videoFile.name });
}
if (videoFile.state === 'FAILED') {
throw new Error(videoFile.state);
}
console.log('Video processing complete: ' + videoFile.uri);
// Edit your video
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'video', uri: videoFile.uri },
{ type: 'text', text: "When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material" }
],
});
if (interaction.output_video?.data) {
fs.writeFileSync('example.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.interactions.VideoContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.File;
import com.google.genai.types.FileState;
import com.google.genai.types.UploadFileConfig;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
// Upload video using the file API
File videoFile =
client.files.upload("Video.mp4", UploadFileConfig.builder().mimeType("video/mp4").build());
while (videoFile.state().isPresent()
&& videoFile.state().get().knownEnum() == FileState.Known.PROCESSING) {
System.out.println("Waiting for video to be processed.");
Thread.sleep(10000);
videoFile = client.files.get(videoFile.name().get(), null);
}
if (videoFile.state().isPresent()
&& videoFile.state().get().knownEnum() == FileState.Known.FAILED) {
throw new IllegalStateException("Video processing failed: " + videoFile.state().get());
}
System.out.println("Video processing complete: " + videoFile.uri().orElse(""));
// Edit your video
Content videoContent = VideoContent.builder().uri(videoFile.uri().get()).build();
Content textContent =
TextContent.builder()
.text(
"When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material")
.build();
List<Content> contents = Arrays.asList(videoContent, textContent);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("example.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"fmt"
"log"
"os"
"time"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Upload video using the file API
videoFile, err := client.Files.UploadFromPath(ctx, "Video.mp4", &genai.UploadFileConfig{
MIMEType: "video/mp4",
})
if err != nil {
log.Fatal(err)
}
for videoFile.State == genai.FileStateProcessing {
fmt.Println("Waiting for video to be processed.")
time.Sleep(10 * time.Second)
videoFile, err = client.Files.Get(ctx, videoFile.Name, nil)
if err != nil {
log.Fatal(err)
}
}
if videoFile.State == genai.FileStateFailed {
log.Fatalf("Video processing failed: %s", videoFile.State)
}
fmt.Printf("Video processing complete: %s\n", videoFile.URI)
// Edit your video
contents := []interactions.Content{
interactions.NewContent(interactions.VideoContent{
URI: genai.Ptr(videoFile.URI),
}),
interactions.NewContent(interactions.TextContent{
Text: "When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("example.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
#!/bin/bash
VIDEO_B64=$(encode_file "$VIDEO_FILE")
curl -sS -w "\n[HTTP %{http_code}]\n" "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: ${API_KEY}" \
-H "Content-Type: application/json" \
-d @- <<EOF > video_editing_response.json
{
"model": "gemini-omni-1.1-flash",
"input": [
{
"type": "user_input",
"content": [
{
"type": "video",
"mime_type": "video/mp4",
"data": "$VIDEO_B64"
},
{
"type": "text",
"text": "When the person touches the mirror, make the mirror ripple beautifully like liquid, and the person's arm turns into reflective mirror material"
}
]
}
],
"response_format": { "type": "video" }
}
EOF
편집된 비디오의 예시:
참고: 데이터를 base64로 직접 전달할 수도 있지만, 비디오는 꽤 클 수 있으므로 File API를 권장해요.
URI로 비디오 검색
response_format의 delivery="uri" 파라미터를 사용해 4MB보다 큰 생성 비디오를 검색해요. 비디오가 ACTIVE가 될 때까지 폴링할 수 있는 Google 호스팅 URI를 반환한 다음 다운로드하세요.
Python
import time
from google import genai
client = genai.Client()
# 1. Request video via URI delivery
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input="A beautiful sunset.",
response_format={"type": "video", "delivery": "uri"}
)
# 2. Extract file name and poll for ACTIVE state
video_output = interaction.output_video
file_name = video_output.uri.split("/")[-1] # Extract ID
print("Waiting for video processing...")
while True:
f_info = client.files.get(name=f"files/{file_name}")
if f_info.state.name == "ACTIVE":
break
elif f_info.state.name == "FAILED":
raise RuntimeError("Generation failed.")
time.sleep(5)
# 3. Download the final video
client.files.download(file=video_output.uri, destination="output.mp4")
JavaScript
import { GoogleGenAI } from '@google/genai';
const ai = new GoogleGenAI({});
// 1. Request video using URI delivery
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: 'A beautiful sunset.',
response_format: { type: 'video', delivery: 'uri' },
});
// 2. Extract filename and poll for ACTIVE state
const videoOutput = interaction.output_video;
const fileId = videoOutput.uri.match(/files\/([a-zA-Z0-9]+)/)[1];
const name = `files/${fileId}`;
console.log("Waiting for video processing...");
while (true) {
const fInfo = await ai.files.get({ name });
if (fInfo.state.name === 'ACTIVE') break;
if (fInfo.state.name === 'FAILED') throw new Error("Generation failed.");
await new Promise(r => setTimeout(r, 5000));
}
// 3. Download the final video
await ai.files.download({
file: videoOutput,
downloadPath: 'output.mp4',
});
console.log("💾 Saved video to output.mp4");
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.CreateModelInteractionResponseFormat;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.ResponseFormat;
import com.google.genai.gaos.models.interactions.VideoContent;
import com.google.genai.gaos.models.interactions.VideoResponseFormat;
import com.google.genai.gaos.models.interactions.VideoResponseFormatDelivery;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.File;
import com.google.genai.types.FileState;
Client client = new Client();
// 1. Request video using URI delivery
VideoResponseFormat videoFormat =
VideoResponseFormat.builder()
.delivery(VideoResponseFormatDelivery.URI)
.build();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.of("A beautiful sunset."))
.responseFormat(CreateModelInteractionResponseFormat.of(ResponseFormat.of(videoFormat)))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
// 2. Extract filename and poll for ACTIVE state
VideoContent videoOutput = interaction.outputVideo().get();
String uri = videoOutput.uri().get();
String[] parts = uri.split("/");
String fileName = parts[parts.length - 1];
System.out.println("Waiting for video processing...");
while (true) {
File fileInfo = client.files.get("files/" + fileName, null);
if (fileInfo.state().isPresent()
&& fileInfo.state().get().knownEnum() == FileState.Known.ACTIVE) {
break;
} else if (fileInfo.state().isPresent()
&& fileInfo.state().get().knownEnum() == FileState.Known.FAILED) {
throw new RuntimeException("Generation failed.");
}
Thread.sleep(5000);
}
// 3. Download the final video
client.files.download(uri, "output.mp4", null);
Go
package main
import (
"context"
"fmt"
"log"
"os"
"strings"
"time"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// 1. Request video using URI delivery
videoFormat := interactions.VideoResponseFormat{
Delivery: interactions.VideoResponseFormatDeliveryURI.ToPointer(),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput("A beautiful sunset."),
ResponseFormat: genai.Ptr(interactions.NewCreateModelInteractionResponseFormat(
interactions.NewResponseFormat(videoFormat),
)),
}),
})
if err != nil {
log.Fatal(err)
}
// 2. Extract filename and poll for ACTIVE state
uri := *res.Interaction.OutputVideo.URI
parts := strings.Split(uri, "/")
fileName := parts[len(parts)-1]
fmt.Println("Waiting for video processing...")
var fileInfo *genai.File
for {
fileInfo, err = client.Files.Get(ctx, "files/"+fileName, nil)
if err != nil {
log.Fatal(err)
}
if fileInfo.State == genai.FileStateActive {
break
} else if fileInfo.State == genai.FileStateFailed {
log.Fatal("Generation failed.")
}
time.Sleep(5 * time.Second)
}
// 3. Download the final video
videoBytes, err := client.Files.Download(ctx, genai.NewDownloadURIFromFile(fileInfo), nil)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("output.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
REST
#!/bin/bash
# 1. Initial request to generate the video
RESPONSE=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-omni-1.1-flash",
"input": "A beautiful sunset over a calm ocean.",
"response_format": {"type": "video", "delivery": "uri"}
}')
# Extract FILE_ID from the URI (e.g., "files/abc-123" -> "abc-123")
FILE_URI=$(echo $RESPONSE | jq -r '.output_video.uri')
FILE_ID=$(echo $FILE_URI | cut -d'/' -f2)
echo "Video requested (ID: $FILE_ID). Waiting for processing..."
# 2. Polling loop
while true; do
# Get current file status
STATUS_JSON=$(curl -s -X GET "https://generativelanguage.googleapis.com/v1beta/files/$FILE_ID?key=$API_KEY")
STATE=$(echo $STATUS_JSON | jq -r '.state')
if [ "$STATE" == "ACTIVE" ]; then
echo "Processing complete! Downloading..."
break
elif [ "$STATE" == "FAILED" ]; then
echo "Error: Generation failed."
exit 1
else
echo "Current state: $STATE... (waiting 5s)"
sleep 5
fi
done
# 3. Final download
curl -L -X GET "https://generativelanguage.googleapis.com/v1beta/files/$FILE_ID:download?alt=media&key=$API_KEY" \
--output "output.mp4"
echo "Done! Video saved to output.mp4"
원시 REST JSON 구조(URI):
{
"steps": [
{ "type": "user_input", "content": [{"type": "text", "text": "..."}] },
{ "type": "thought", "content": [{"text": "...", "type": "thought"}] },
{
"type": "model_output",
"content": [
{
"type": "video",
"mime_type": "video/mp4",
"uri": "https://generativelanguage.googleapis.com/v1beta/files/...:download?alt=media"
}
]
}
],
"id": "v1_...",
"status": "completed",
"model": "gemini-omni-1.1-flash",
"object": "interaction"
}
참고: 현재 GET /v1beta/interactions/{id}를 호출하면 상호작용이 원래 delivery: "uri"로 생성됐더라도 data 필드에 인라인 base64 데이터로 비디오를 반환해요. uri 필드는 초기 생성 응답 또는 Server-Sent Events(SSE) 스트림에만 존재하는 것이 보장돼요.
비디오 확장 (Video extension)
클립 끝에 매끄러운 연속 장면을 생성해 기존 비디오를 확장해요. 프롬프트에서 비디오가 어떻게 계속되길 원하는지 설명하세요. 예: "Extend this video" 또는 "Continue the scene: the camera pans across the mountains". 모델은 입력 비디오를 분석해 3~10초의 연속 장면을 생성해요.
다음을 확장할 수 있어요.
- 모델이 생성한 비디오(멀티 턴):
previous_interaction_id를 참조해 이전에 생성된 비디오를 확장해요. - 업로드된 비디오: 확장 프롬프트와 함께 업로드한 비디오 파일(Files API 경유)을 제공해요.
Python
import base64
from google import genai
client = genai.Client()
# Upload your video using the Files API
video_file = client.files.upload(file="my_video.mp4")
# Extend the video using prompt-based extension
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "video", "uri": video_file.uri},
{"type": "text", "text": "Continue the scene."}
],
)
with open("extended.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
// Upload your video using the Files API
let videoFile = await ai.files.upload({
file: 'my_video.mp4',
});
while (videoFile.state === 'PROCESSING') {
await new Promise(r => setTimeout(r, 10000));
videoFile = await ai.files.get({ name: videoFile.name });
}
// Extend the video using prompt-based extension
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'video', uri: videoFile.uri },
{ type: 'text', text: 'Continue the scene.' }
],
});
if (interaction.output_video?.data) {
fs.writeFileSync('extended.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.interactions.VideoContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.File;
import com.google.genai.types.UploadFileConfig;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
// Upload your video using the Files API
File videoFile =
client.files.upload(
"my_video.mp4", UploadFileConfig.builder().mimeType("video/mp4").build());
// Extend the video using prompt-based extension
Content videoContent = VideoContent.builder().uri(videoFile.uri().get()).build();
Content textContent = TextContent.builder().text("Continue the scene.").build();
List<Content> contents = Arrays.asList(videoContent, textContent);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("extended.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Upload your video using the Files API
videoFile, err := client.Files.UploadFromPath(ctx, "my_video.mp4", &genai.UploadFileConfig{
MIMEType: "video/mp4",
})
if err != nil {
log.Fatal(err)
}
// Extend the video using prompt-based extension
contents := []interactions.Content{
interactions.NewContent(interactions.VideoContent{
URI: genai.Ptr(videoFile.URI),
}),
interactions.NewContent(interactions.TextContent{
Text: "Continue the scene.",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("extended.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" -H "Content-Type: application/json" -d '{
"model": "gemini-omni-1.1-flash",
"input": [
{"type": "video", "uri": "'"$VIDEO_URI"'"},
{"type": "text", "text": "Continue the scene."}
]
}'
브라우저에서 비디오 태그를 지원하지 않습니다.
브라우저에서 비디오 태그를 지원하지 않습니다.
참조 미디어로 확장
프롬프트와 함께 input 배열에 참조 이미지를 제공해 확장된 비디오에 새 캐릭터나 요소를 도입할 수 있어요.
Python
import base64
from google import genai
client = genai.Client()
# Upload base video and reference image using the Files API
video_file = client.files.upload(file="my_video.mp4")
character_img = client.files.upload(file="character.png")
# Extend the video while introducing the reference character
interaction = client.interactions.create(
model="gemini-omni-1.1-flash",
input=[
{"type": "video", "uri": video_file.uri},
{"type": "image", "uri": character_img.uri},
{"type": "text", "text": "Extend this video: have the character shown in <IMAGE_REF_0> enter the scene and wave."}
],
)
with open("extended_with_character.mp4", "wb") as f:
f.write(base64.b64decode(interaction.output_video.data))
JavaScript
import { GoogleGenAI } from '@google/genai';
import * as fs from 'fs';
const ai = new GoogleGenAI({});
// Upload base video and reference image using the Files API
let videoFile = await ai.files.upload({ file: 'my_video.mp4' });
let characterImg = await ai.files.upload({ file: 'character.png' });
while (videoFile.state === 'PROCESSING' || characterImg.state === 'PROCESSING') {
await new Promise(r => setTimeout(r, 10000));
videoFile = await ai.files.get({ name: videoFile.name });
characterImg = await ai.files.get({ name: characterImg.name });
}
// Extend the video while introducing the reference character
const interaction = await ai.interactions.create({
model: 'gemini-omni-1.1-flash',
input: [
{ type: 'video', uri: videoFile.uri },
{ type: 'image', uri: characterImg.uri },
{ type: 'text', text: 'Extend this video: have the character shown in <IMAGE_REF_0> enter the scene and wave.' }
],
});
if (interaction.output_video?.data) {
fs.writeFileSync('extended_with_character.mp4', Buffer.from(interaction.output_video.data, 'base64'));
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.Content;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.interactions.VideoContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.types.File;
import com.google.genai.types.UploadFileConfig;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
Client client = new Client();
// Upload base video and reference image using the Files API
File videoFile =
client.files.upload(
"my_video.mp4", UploadFileConfig.builder().mimeType("video/mp4").build());
File characterImg =
client.files.upload(
"character.png", UploadFileConfig.builder().mimeType("image/png").build());
// Extend the video while introducing the reference character
Content videoContent = VideoContent.builder().uri(videoFile.uri().get()).build();
Content imageContent = ImageContent.builder().uri(characterImg.uri().get()).build();
Content textContent =
TextContent.builder()
.text(
"Extend this video: have the character shown in <IMAGE_REF_0> enter the scene and wave.")
.build();
List<Content> contents = Arrays.asList(videoContent, imageContent, textContent);
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-omni-1.1-flash"))
.input(InteractionsInput.ofContent(contents))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
if (interaction.outputVideo().isPresent() && interaction.outputVideo().get().data().isPresent()) {
byte[] videoBytes = Base64.getDecoder().decode(interaction.outputVideo().get().data().get());
Files.write(Paths.get("extended_with_character.mp4"), videoBytes);
}
Go
package main
import (
"context"
"encoding/base64"
"log"
"os"
"google.golang.org/genai"
"google.golang.org/genai/interactions/models/interactions"
"google.golang.org/genai/interactions/models/operations"
)
func main() {
ctx := context.Background()
client, err := genai.NewClient(ctx, nil)
if err != nil {
log.Fatal(err)
}
// Upload base video and reference image using the Files API
videoFile, err := client.Files.UploadFromPath(ctx, "my_video.mp4", &genai.UploadFileConfig{
MIMEType: "video/mp4",
})
if err != nil {
log.Fatal(err)
}
characterImg, err := client.Files.UploadFromPath(ctx, "character.png", &genai.UploadFileConfig{
MIMEType: "image/png",
})
if err != nil {
log.Fatal(err)
}
// Extend the video while introducing the reference character
contents := []interactions.Content{
interactions.NewContent(interactions.VideoContent{
URI: genai.Ptr(videoFile.URI),
}),
interactions.NewContent(interactions.ImageContent{
URI: genai.Ptr(characterImg.URI),
}),
interactions.NewContent(interactions.TextContent{
Text: "Extend this video: have the character shown in <IMAGE_REF_0> enter the scene and wave.",
}),
}
res, err := client.Interactions.Create(ctx, operations.CreateInteractionRequest{
Body: operations.NewCreateInteractionRequestBody(interactions.CreateModelInteraction{
Model: interactions.Model("gemini-omni-1.1-flash"),
Input: interactions.NewInteractionsInput(contents),
}),
})
if err != nil {
log.Fatal(err)
}
if res.Interaction.OutputVideo != nil && res.Interaction.OutputVideo.Data != nil {
videoBytes, err := base64.StdEncoding.DecodeString(*res.Interaction.OutputVideo.Data)
if err != nil {
log.Fatal(err)
}
if err := os.WriteFile("extended_with_character.mp4", videoBytes, 0644); err != nil {
log.Fatal(err)
}
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?key=$API_KEY" -H "Content-Type: application/json" -d '{
"model": "gemini-omni-1.1-flash",
"input": [
{"type": "video", "uri": "'$VIDEO_URI'"},
{"type": "image", "uri": "'$CHARACTER_IMG_URI'"},
{"type": "text", "text": "Extend this video: have the character shown in <IMAGE_REF_0> enter the scene and wave."}
]
}'
브라우저에서 비디오 태그를 지원하지 않습니다.
팁: 선택적으로 프롬프팅만으로 원하는 확장 모드가 생성되지 않으면 generation_config 아래 video_config에서 "task": "extend"를 설정할 수 있어요. 다만 task 필드는 모델에 엄격한 제약을 추가하므로 먼저 프롬프팅을 주로 사용할 것을 권장해요.
확장 제약과 가이드라인
비디오를 확장할 때 다음 규칙과 제약을 기억하세요.
- 업로드된 비디오의 음성 대화: 현재 누군가 말하고 있는 업로드된 비디오를 확장해 추가 대화를 추가할 수는 없어요(캐릭터가 조용히 있거나 프롬프트가 대화를 추가하지 않으면 지원돼요).
- 멀티 턴 음성 확장: 이전에 생성된 비디오를 멀티 턴(
previous_interaction_id)으로 확장할 때는 음성 대화나 음성 생성을 지원해요. - 클립 끝만: 확장은 비디오 끝에 이어 붙이는 것만 가능해요. 콘텐츠를 앞에 추가하거나 클립 중간을 확장할 수는 없어요.
- 길이 한도: 확장용 입력 비디오는 업로드 시 10초 이하여야 해요(멀티 턴 사용 시 제외).
- 지역 가용성: 업로드된 비디오 확장은 현재 EEA(유럽 경제 지역), 스위스, 영국 사용자에게는 사용할 수 없어요(모델이 생성한 비디오 확장은 모든 가용 지역에서 지원돼요).
모범 사례 (Best practices)
- 큰 비디오에는 URI 전달 사용: 4MB(가능할 때 >720p)보다 큰 비디오는
response_format에delivery="uri"를 사용해 페이로드 크기 제한을 피하세요. - 성능 최적화: 더 빠른 동기식 unary 생성을 위해
background=false,store=false,stream=false로 설정하세요.store=false로 설정하면 생성된 비디오를previous_interaction_id로 이후 턴에서 편집할 수 없다는 점에 유의하세요. - 프롬프트 정밀도: 자세한 내용은 prompt guidance 섹션 참고.
제한 사항 (Limitations)
- 미성년자가 포함된 이미지 업로드·편집은 EEA(유럽 경제 지역), 스위스, 영국에서 지원되지 않아요.
- 특정 알아볼 수 있는 인물이 포함된 이미지의 업로드·편집은 지원되지 않아요.
- 업로드된 비디오의 편집·확장은 현재 EEA, 스위스, 영국 사용자에게는 사용할 수 없어요(모델이 생성한 비디오의 편집·확장은 지원돼요).
- 편집·확장용 입력 비디오는 업로드 시 10초 이하여야 해요(멀티 턴에서 모델이 생성한 비디오를 확장하는 경우 제외).
- 비디오 확장은 비디오 끝에 이어 붙이는 것만 가능해요. 앞에 추가하거나 클립 중간을 확장하는 것은 지원되지 않아요.
- 누군가 말하고 있는 업로드된 비디오에 추가 대화를 더하기 위해 확장할 수는 없어요(캐릭터는 조용히 있을 수 있고,
previous_interaction_id로 멀티 턴 확장을 사용할 수 있어요). - 음성 편집(Voice editing)은 지원되지 않아요.
- 오디오 참조 업로드는 현재 API 버전에서 지원되지 않아요.
- 비디오 참조는 닮음(likeness)에 가장 잘 작동하며, 비디오 참조의 오디오는 무시돼요. 비디오 참조는 각각 최대 3초, 최대 3개의 클립을 지원해요.
- 여러 비디오에 걸친 참조 또는 추론은 지원되지 않아요. 다중 비디오 프롬프팅을 시도하면 모델 성능이 저하되거나 예상치 못한 출력이 발생할 수 있어요.
- 프로비저닝된 처리량은 지원되지 않아요.
- 시스템 지침, temperature,
top_p, stop sequences, 네거티브 프롬프트는 지원되지 않아요(일반 프롬프트에 네거티브를 넣을 수 있어요. 예: "Do not do X"). - 미디어 소스로 YouTube 비디오를 사용하는 것은 지원되지 않아요.
기술 세부 사항 (Technical details)
- 모든 생성 비디오에는 SynthID 워터마킹이 포함돼요. 시청자에게는 보이지 않지만 출처 검증을 위해 프로그래밍 방식으로 감지할 수 있어요.
- 비디오 생성 시간은 길이, 해상도, 현재 API 부하에 따라 달라져요. 더 길고 해상도가 높은 비디오는 생성에 더 많은 시간이 걸려요.
- Omni는 입력 프롬프트와 생성된 비디오 모두에 콘텐츠 안전 필터를 적용해요(지역에 따라 다름). 사용 정책을 위반하는 프롬프트는 차단돼요.
- 영어(EN)는 완전히 지원되지만 다른 언어는 평가되지 않았으므로 작동할 수는 있지만 결과가 달라질 수 있어요.
Gemini Omni Flash 프롬프트 가이드
이 섹션은 Gemini Omni Flash를 효과적으로 프롬프팅하는 팁과 예시를 담고 있어요.
단일 장면 (Single scene)
기본적으로 Omni Flash는 몇 가지 다른 샷이 있는 비디오를 만들려고 해요. 프롬프트에 기반해 흥미로운 내러티브를 만들려고 시도해요.
출력 비디오에 단일 장면이 필요하다면 이를 프롬프팅해야 해요.
- 단일 끊김 없는 장면에서(In a single unbroken scene)
- 단일 연속 샷에서(In a single continuous shot)
- 장면 컷 없이(No scene cuts)
예를 들어:
Continuous, unbroken handheld shot of a fluffy tabby cat sitting on a sunny windowsill, looking out into a leafy garden. The cat's tail twitches slowly, and its ears rotate slightly toward ambient noises. Sunbeams illuminate dust motes in the air. Sound design: Gentle breeze, distant bird chirps. No dialogue.
원하지 않는 요소 제거
생성된 비디오에 원하지 않는 것이 있으면 간단한 네거티브 프롬프트를 포함해 피하세요.
- 대화 없음(No dialogue)
- 장식 없음(No embellishments)
- 추가 음향 효과 없음(No extra sound effects)
편집용 프롬프트
비디오 편집에는 간단한 프롬프트가 가장 잘 작동해요. 지나치게 묘사적인 프롬프트는 의도하지 않은 변경을 초래할 수 있어요.
간단한 편집 프롬프트의 더 많은 예시:
- 이 비디오를 애니메이션으로 만들어줘(Make this video anime)
- 이 사람에게 유행하는 모자를 씌워줘(Put a fashionable hat on this person)
- 조명을 더 극적으로 바꿔줘(Change the lighting to be more dramatic)
- 간판의 텍스트를 "Omni Flash"로 바꿔줘(Change the text on the sign to say "Omni Flash")
비디오의 특정 측면을 편집할 때는 시각적 일관성을 유지하기 위해 "Keep everything else the same"을 포함하세요.
이 기법을 적용하는 방법을 보여주는 몇 가지 예시:
- 피해야 할 것:
In the video of the man sitting on the sofa, please add a small black cat that runs from the right side of the screen, jumps onto his lap, and then he starts to stroke its head while looking down. - 단순화:
Add a cat that jumps onto his lap, he begins to pet it. Keep everything else the same. - 피해야 할 것:
Please remove the cell phone that the person is holding in their hand and fill in the background so it looks like they are just holding their hand empty. - 단순화:
Make the phone invisible. Keep everything else the same.
오디오 프롬프팅
기본적으로 모델은 비디오에 적절한 오디오 트랙을 생성하려고 해요. 항상 원하는 것이 아닐 수 있어요. 프롬프트로 원하는 오디오 유형을 설명할 수 있어요. 특히 비디오에 음악을 원한다면 중요해요.
- 차분한 배경 음악을 포함해줘(Include calm background music)
- 비디오가 고에너지 테크노 비트를 가짐(The video has a high energy techno beat)
- 오디오가 배경에서 노래를 재생하는 낮고 맑은 라디오 방송임(The audio is a low tinny radio broadcast in the background, playing a song)
이벤트 타이밍
비디오의 특정 시점에 무엇인가 일어나도록 프롬프팅할 수 있어요. 정밀한 구문은 필요 없고 자연어를 사용할 수 있어요. 이는 자신만의 장면 컷, 리듬, 빠른 연속 시퀀스를 만드는 데 특히 유용해요.
- 3초 후, 여자가 장면에 들어옴(After 3 seconds, a woman enters the scene.)
- 5초에 배경 오디오에서 코러스 시작(At 5s the chorus starts in the background audio.)
- 2초마다 새 프레임으로 컷(Every 2s cut to a new frame.)
- 빠른 연속 시퀀스에서 매 0.5초(24fps에서 12프레임)마다 장면을 새 위치로 변경(In a rapid fire sequence, every half a second (12 frames at 24fps) change the scene to a new location.)
타임코드 구문도 사용할 수 있어요.
[0-3s] A person is walking
[3-6s] They stop and turn around
[6-10s] They start running
메타 프롬프팅
Gemini Omni Flash에게 비디오 생성의 일반적인 품질이나 원칙에 주의를 기울이도록 요청할 수 있어요.
- 매우 풍부하고 상세하지만 완전히 자연스러운 장면을 만들기 위해 마이크로 디테일, 표정, 타이밍을 고려하세요(CONSIDER micro-detail, expression and timing to create a very rich, detailed but entirely natural scene.)
- 캐릭터와 환경에 대한 설명을 매우 상세하게 하세요(Be extremely detailed in your descriptions of characters and environments). 캐릭터에 의상 디자인 원칙을 적용하세요(Apply costume design principles to characters). 장면의 사람, 항목, 객체에 대해 매우 구체적이어야 해요.
- 장면이 사실적이고 자연스럽게 느껴지도록 배경 요소에 충분히 적절한 디테일을 포함하세요(Include plenty of appropriate detail in the background elements to make the scene feel realistic and natural).
- 매 1초마다 다른 희귀한
[thing]을 보여주는 빠른 연속 비디오를 만들고, 경쾌한 음악을 넣고, 항목을 라벨링하는 텍스트를 포함하세요(Make a rapid fire video that shows a different rare[thing]every 1s, upbeat music, include text to label the thing).
비디오에서 텍스트
비디오에 텍스트를 포함하도록 프롬프팅할 수 있고, Gemini Omni가 정확하고 읽을 수 있는 방식으로 렌더링해요. 비디오에 자연적으로 발생하는 텍스트가 있다면, 배경 요소에서도 무엇을 말해야 하는지 정의하는 것이 도움이 될 수 있어요.
- 한 번에 화면에 단어 하나씩: "did, you, know, that, Omni, can, do, awesome, text?" 각 단어는 다른 애니메이션 스타일로 1초씩 나타남. 대화 없음(No dialogue).
- "This is an AI generation by Omni"라고 쓰인 거리 간판이 있음(There is a street sign that says: "This is an AI generation by Omni"). "All you need AI"라고 쓰인 상점 정면이 있음(There is a storefront that says: "All you need AI"). 번호판이 "OMNI1.1"인 차가 있음(There's a car with the number plate: "OMNI1.1").
비디오 확장 프롬프트
Gemini Omni 1.1 Flash에서는 "Extend this video" 또는 "The scene continues" 같은 프롬프트로 비디오를 확장할 수 있어요. 비디오를 10초씩, 최대 총 길이 40초까지 확장할 수 있어요.
Omni는 원본 비디오의 마지막 10초를 컨텍스트로 사용해 비디오, 움직임, 캐릭터, 오디오를 일관되게 유지하는 확장을 만들어요. 입력 비디오의 마지막 프레임 중 일부는 전환이 매끄럽도록 편집돼요.
확장 시 이 가이드의 모든 Omni 프롬프팅 팁이 여전히 적용돼요.
- 확장된 장면의 오디오를 설명하세요, 특히 변경이 필요하다면:
"The music continues into the chorus" - 장면이 계속되는지, 아니면 새 장면으로 샷 컷이 있는지 설명하세요(같은 캐릭터일 수도 있음):
"Show the same characters in the next scene" - 출력을 정확하게 유지하거나 새 캐릭터를 도입하려면 확장 시 이미지와 비디오를 참조로 포함하세요:
"The person shown in the reference image enters the scene","The dog in the reference video <VIDEO_REF_0> jumps onto the sofa" - 타임스탬프나 타임코드 구문을 사용한다면 0s는 비디오의 확장된 부분의 시작을 가리켜요. 10초 비디오를 확장한다면 이 프롬프트의 장면 컷은 12초 후에 발생해요:
"After 2s cut to a new scene with the same characters"
프롬프트에서 태그로 이미지·비디오 역할 설정
태그를 사용해 업로드된 미디어를 특정 생성 역할에 바인딩할 수 있어요. 이를 통해 각 이미지·비디오가 시작 프레임인지, 최종 프레임인지, 참조인지 지정할 수 있어요.
1. 간단한 태그 (권장)
미디어 역할이 프롬프트에서 명확한 단순한 경우, 이미지와 비디오를 역할에 직접 바인딩할 수 있어요.
- ``: 이미지를 비디오의 시작 프레임으로 사용. 예:
<FIRST_FRAME> a woman is walking - ``: 이미지를 전환할 비디오의 최종 프레임으로 사용.
<FIRST_FRAME>와 함께 사용해야 해요. 예:<FIRST_FRAME> <LAST_FRAME> a woman is walking - ``: 이미지를 참조로 사용. 예:
in the style of <IMAGE_REF_0> a woman <IMAGE_REF_1> is walking(첫 이미지의 스타일 참조와 둘째 이미지의 피사체 참조를 결합). 이미지 참조는 0부터 시작해요. - ``: 비디오를 캐릭터나 객체 참조로 사용. 예:
the person in <VIDEO_REF_0> is playing the violin. 비디오 참조도 0부터 시작해요.
다음은 6개의 참조 이미지가 있는 예시예요.
[0-3s] A studio fashion sequence. Starting with woman <IMAGE_REF_0>, she is holding <IMAGE_REF_1>
[3-6s] Then we see the man <IMAGE_REF_2> holding <IMAGE_REF_3>
[6-10s] And finally another woman <IMAGE_REF_4> who is holding <IMAGE_REF_5> while walking.
2. 소스와 참조 선언
여러 미디어 입력과 여러 역할이 있는 더 복잡한 경우, 자연어 지침과 짝을 이룬 명시적 접두사 태그를 사용할 수 있어요. 이러한 소스와 참조를 프롬프트 시작 부분에 선언해야 해요.
[# Sources <FIRST_FRAME>@Image1]첫 이미지를 시작 프레임으로 사용.[# Sources <FIRST_FRAME>@Image1 <LAST_FRAME>@Image2]첫 이미지와 둘째 이미지를 각각 시작 프레임과 최종 프레임으로 사용.[# Sources <FIRST_FRAME>@Image1 <LAST_FRAME>@Image1]첫 이미지를 첫 프레임과 마지막 프레임 모두로 사용해 루프하는 비디오를 만듦.[# Sources <FIRST_FRAME>@Image1] [# References <IMAGE_REF_0>@Image2]첫 이미지를 시작 프레임으로, 둘째 이미지를 참조로 사용.[# Sources <VIDEO_0>@Video1]비디오를 편집·수정할 기본 소스 비디오로 사용.[# Sources <PREVIOUS_VIDEO>@Video1]이전 턴의 비디오를 확장용으로 사용.[# References <IMAGE_REF_0>@Image1]첫 이미지를 참조로 사용.[# References <IMAGE_REF_1>@Image2]둘째 이미지를 참조로 사용.[# References <IMAGE_REF_0>@Image1 <IMAGE_REF_1>@Image2]두 이미지를 모두 참조로 사용.[# References <VIDEO_REF_0>@Video1]첫 비디오를 참조로 사용.[# References <IMAGE_REF_0>@Image1 <VIDEO_REF_0>@Video1]이미지와 비디오를 모두 참조로 사용.
프롬프트 끝에 안내 지침을 추가하세요.
- 시작 프레임의 경우:
"Use this image as the starting frame." - 시작·끝 프레임을 통한 루프 비디오의 경우:
"Use this image as the first frame and the last frame." - 참조 이미지의 경우:
"Use the given image(s) as references for video generation. The images should not be used as literal initial frames." - 참조 비디오의 경우:
"Use the given video(s) as references. Do not use them as a source for video editing."
소스와 참조 선언이 있는 프롬프트의 몇 가지 예시:
시작 프레임과 참조 이미지의 결합:
[# Sources <FIRST_FRAME>@Image1] [# References <IMAGE_REF_0>@Image2] a woman <IMAGE_REF_0> is walking. Use Image1 as the starting frame. Use Image2 as a reference for the video generation.
캐릭터 참조 비디오와 객체 참조 이미지의 결합:
[# References <IMAGE_REF_0>@Image1 <VIDEO_REF_0>@Video1] The woman in <VIDEO_REF_0> is playing the violin shown in <IMAGE_REF_0>. Use Video1 as a character reference and Image1 as an object reference.
다음 단계 (What's next)
- Omni Quickstart Colab에서 Gemini Omni Flash를 실험해 보세요.
- Introduction to prompt design으로 더 나은 프롬프트를 작성하는 법을 배워 보세요.
더 알아보기 (Learn more)
- Interactions API 문서로 비디오 생성 API를 이해해 보세요.
- Files API로 비디오 업로드 방법을 익혀 보세요.
- Gemini Omni Flash 모델 카드를 확인해 보세요.