or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

auth-tokens.mdbatch.mdcaching.mdchat.mdclient.mdcontent-generation.mdembeddings.mdfile-search-stores.mdfiles.mdfunction-calling.mdimage-generation.mdindex.mdlive.mdmcp.mdmodels.mdoperations.mdtuning.mdvideo-generation.md

video-generation.mddocs/

0

# Video Generation

1

2

The Models module provides video generation capabilities using Veo models, supporting text-to-video, image-to-video, and video-to-video generation as long-running operations.

3

4

## Capabilities

5

6

### generateVideos

7

8

Generate videos from text, images, or existing videos using Veo models. This is a long-running operation that requires polling for completion.

9

10

```typescript { .api }

11

/**

12

* Generate videos from text/images (returns long-running operation)

13

* @param params - Video generation parameters

14

* @returns Promise resolving to video generation operation

15

*/

16

function generateVideos(

17

params: GenerateVideosParameters

18

): Promise<GenerateVideosOperation>;

19

20

interface GenerateVideosParameters {

21

/** Model name (e.g., 'veo-2.0-generate-001') */

22

model: string;

23

/** Text prompt for video generation */

24

prompt?: string;

25

/** Source image for image-to-video */

26

image?: BlobImageUnion;

27

/** Source video for video-to-video */

28

video?: BlobVideoUnion;

29

/** Source reference */

30

source?: SourceUnion;

31

/** Video generation configuration */

32

config?: GenerateVideosConfig;

33

}

34

35

interface GenerateVideosOperation {

36

/** Operation name (used for polling status) */

37

name?: string;

38

/** Whether operation is complete */

39

done?: boolean;

40

/** Response when operation completes successfully */

41

response?: GenerateVideosResponse;

42

/** Error if operation failed */

43

error?: Status;

44

/** Operation metadata */

45

metadata?: GenerateVideosMetadata;

46

}

47

```

48

49

**Usage Examples:**

50

51

```typescript

52

import { GoogleGenAI } from '@google/genai';

53

54

const client = new GoogleGenAI({ apiKey: 'YOUR_API_KEY' });

55

56

// Text-to-video generation

57

const operation = await client.models.generateVideos({

58

model: 'veo-2.0-generate-001',

59

prompt: 'A serene lake with mountains in the background, sunrise time lapse'

60

});

61

62

console.log('Operation started:', operation.name);

63

64

// Poll for completion

65

while (!operation.done) {

66

await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds

67

const updated = await client.operations.getVideosOperation({

68

operation: operation.name!

69

});

70

71

if (updated.done) {

72

if (updated.response) {

73

console.log('Video generated successfully');

74

const videoUri = updated.response.generatedVideos?.[0]?.video?.uri;

75

console.log('Video URI:', videoUri);

76

} else if (updated.error) {

77

console.error('Video generation failed:', updated.error);

78

}

79

break;

80

}

81

}

82

83

// With configuration

84

const configuredOp = await client.models.generateVideos({

85

model: 'veo-2.0-generate-001',

86

prompt: 'A robot walking through a futuristic city',

87

config: {

88

aspectRatio: '16:9',

89

durationSeconds: 8

90

}

91

});

92

```

93

94

### Operations Management

95

96

Poll and manage video generation operations.

97

98

```typescript { .api }

99

/**

100

* Get video generation operation status

101

* @param params - Operation parameters

102

* @returns Promise resolving to operation status

103

*/

104

function getVideosOperation(

105

params: OperationGetParameters<GenerateVideosResponse, GenerateVideosOperation>

106

): Promise<GenerateVideosOperation>;

107

108

interface OperationGetParameters<T, U> {

109

/** Operation name from initial generateVideos call */

110

operation: string;

111

}

112

```

113

114

**Usage Examples:**

115

116

```typescript

117

// Start video generation

118

const operation = await client.models.generateVideos({

119

model: 'veo-2.0-generate-001',

120

prompt: 'Waves crashing on a beach'

121

});

122

123

// Poll operation status

124

const pollOperation = async (opName: string) => {

125

let op = await client.operations.getVideosOperation({

126

operation: opName

127

});

128

129

while (!op.done) {

130

console.log('Operation in progress...');

131

if (op.metadata) {

132

console.log('Progress:', op.metadata);

133

}

134

135

await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10s

136

137

op = await client.operations.getVideosOperation({

138

operation: opName

139

});

140

}

141

142

return op;

143

};

144

145

const result = await pollOperation(operation.name!);

146

147

if (result.response?.generatedVideos) {

148

result.response.generatedVideos.forEach((genVideo, index) => {

149

console.log(`Video ${index}:`, genVideo.video?.uri);

150

});

151

}

152

```

153

154

## Types

155

156

### GenerateVideosConfig

157

158

Configuration options for video generation.

159

160

```typescript { .api }

161

interface GenerateVideosConfig {

162

/** Aspect ratio (e.g., '16:9', '9:16', '1:1') */

163

aspectRatio?: string;

164

/** Video duration in seconds */

165

durationSeconds?: number;

166

/** Number of videos to generate */

167

numberOfVideos?: number;

168

/** Negative prompt (things to avoid) */

169

negativePrompt?: string;

170

/** Frame rate (fps) */

171

frameRate?: number;

172

/** Guidance scale */

173

guidanceScale?: number;

174

/** Random seed for reproducibility */

175

seed?: number;

176

/** Safety filter level */

177

safetyFilterLevel?: SafetyFilterLevel;

178

/** Include RAI information */

179

includeRaiReason?: boolean;

180

/** Output video codec */

181

outputVideoType?: string;

182

}

183

```

184

185

### GenerateVideosResponse

186

187

Response from completed video generation operation.

188

189

```typescript { .api }

190

interface GenerateVideosResponse {

191

/** Generated videos */

192

generatedVideos?: GeneratedVideo[];

193

}

194

195

interface GeneratedVideo {

196

/** Video data */

197

video?: Video;

198

/** RAI (Responsible AI) information */

199

rai?: Rai;

200

}

201

202

interface Video {

203

/** Video URI (GCS path or download URI) */

204

uri?: string;

205

/** Processing state */

206

state?: FileState;

207

}

208

```

209

210

### GenerateVideosMetadata

211

212

Metadata about the video generation operation.

213

214

```typescript { .api }

215

interface GenerateVideosMetadata {

216

/** Operation create time */

217

createTime?: string;

218

/** Operation start time */

219

startTime?: string;

220

/** Operation update time */

221

updateTime?: string;

222

/** Progress percentage (0-100) */

223

progressPercentage?: number;

224

}

225

```

226

227

### Status

228

229

Error information if operation failed.

230

231

```typescript { .api }

232

interface Status {

233

/** Error code */

234

code?: number;

235

/** Error message */

236

message?: string;

237

/** Additional error details */

238

details?: unknown[];

239

}

240

```

241

242

### BlobImageUnion and BlobVideoUnion

243

244

Input media types.

245

246

```typescript { .api }

247

/** Image blob for image-to-video */

248

type BlobImageUnion = Blob;

249

250

/** Video blob for video-to-video */

251

type BlobVideoUnion = Blob;

252

253

interface Blob {

254

/** MIME type (e.g., 'image/png', 'video/mp4') */

255

mimeType?: string;

256

/** Base64-encoded data */

257

data?: string;

258

}

259

```

260

261

### Enumerations

262

263

```typescript { .api }

264

enum FileState {

265

STATE_UNSPECIFIED = 'STATE_UNSPECIFIED',

266

PROCESSING = 'PROCESSING',

267

ACTIVE = 'ACTIVE',

268

FAILED = 'FAILED'

269

}

270

271

enum SafetyFilterLevel {

272

BLOCK_LOW_AND_ABOVE = 'BLOCK_LOW_AND_ABOVE',

273

BLOCK_MEDIUM_AND_ABOVE = 'BLOCK_MEDIUM_AND_ABOVE',

274

BLOCK_ONLY_HIGH = 'BLOCK_ONLY_HIGH',

275

BLOCK_NONE = 'BLOCK_NONE'

276

}

277

```

278

279

## Complete Examples

280

281

### Text-to-Video with Polling Helper

282

283

```typescript

284

import { GoogleGenAI, GenerateVideosOperation } from '@google/genai';

285

286

const client = new GoogleGenAI({ apiKey: 'YOUR_API_KEY' });

287

288

// Helper function to poll until completion

289

async function pollVideoOperation(

290

client: GoogleGenAI,

291

operationName: string,

292

pollIntervalMs: number = 10000

293

): Promise<GenerateVideosOperation> {

294

let operation = await client.operations.getVideosOperation({

295

operation: operationName

296

});

297

298

while (!operation.done) {

299

console.log(`Polling operation... ${operation.metadata?.progressPercentage || 0}%`);

300

await new Promise(resolve => setTimeout(resolve, pollIntervalMs));

301

302

operation = await client.operations.getVideosOperation({

303

operation: operationName

304

});

305

}

306

307

return operation;

308

}

309

310

// Generate video

311

const operation = await client.models.generateVideos({

312

model: 'veo-2.0-generate-001',

313

prompt: 'A time-lapse of a flower blooming in spring',

314

config: {

315

aspectRatio: '16:9',

316

durationSeconds: 5,

317

numberOfVideos: 1

318

}

319

});

320

321

console.log('Video generation started:', operation.name);

322

323

// Wait for completion

324

const completed = await pollVideoOperation(client, operation.name!);

325

326

if (completed.response?.generatedVideos?.[0]?.video?.uri) {

327

console.log('Video ready:', completed.response.generatedVideos[0].video.uri);

328

} else if (completed.error) {

329

console.error('Video generation failed:', completed.error.message);

330

}

331

```

332

333

### Image-to-Video Generation

334

335

```typescript

336

import { GoogleGenAI } from '@google/genai';

337

import * as fs from 'fs';

338

339

const client = new GoogleGenAI({ apiKey: 'YOUR_API_KEY' });

340

341

// Read image as base64

342

const imageData = fs.readFileSync('./start_frame.png', 'base64');

343

344

// Generate video from image

345

const operation = await client.models.generateVideos({

346

model: 'veo-2.0-generate-001',

347

prompt: 'Animate this scene with gentle camera movement',

348

image: {

349

data: imageData,

350

mimeType: 'image/png'

351

},

352

config: {

353

aspectRatio: '16:9',

354

durationSeconds: 8,

355

frameRate: 24

356

}

357

});

358

359

console.log('Image-to-video generation started:', operation.name);

360

```

361

362

### Video-to-Video (Style Transfer)

363

364

```typescript

365

const videoData = fs.readFileSync('./source_video.mp4', 'base64');

366

367

const operation = await client.models.generateVideos({

368

model: 'veo-2.0-generate-001',

369

prompt: 'Transform this video into an animated cartoon style',

370

video: {

371

data: videoData,

372

mimeType: 'video/mp4'

373

},

374

config: {

375

durationSeconds: 10,

376

guidanceScale: 7.5

377

}

378

});

379

380

console.log('Video-to-video generation started:', operation.name);

381

```

382

383

### Multiple Video Variants

384

385

```typescript

386

// Generate multiple variations

387

const operation = await client.models.generateVideos({

388

model: 'veo-2.0-generate-001',

389

prompt: 'A cat playing with a ball of yarn',

390

config: {

391

aspectRatio: '9:16',

392

durationSeconds: 6,

393

numberOfVideos: 4,

394

negativePrompt: 'blurry, low quality, distorted'

395

}

396

});

397

398

// Wait for completion

399

const completed = await pollVideoOperation(client, operation.name!);

400

401

// Process all generated videos

402

completed.response?.generatedVideos?.forEach((genVideo, index) => {

403

if (genVideo.video?.uri) {

404

console.log(`Video ${index + 1}:`, genVideo.video.uri);

405

406

if (genVideo.rai) {

407

console.log(` RAI info:`, genVideo.rai);

408

}

409

}

410

});

411

```

412

413

### Reproducible Generation with Seeds

414

415

```typescript

416

// Generate with specific seed for reproducibility

417

const operation1 = await client.models.generateVideos({

418

model: 'veo-2.0-generate-001',

419

prompt: 'A sunset over the ocean',

420

config: {

421

seed: 12345,

422

aspectRatio: '16:9',

423

durationSeconds: 5

424

}

425

});

426

427

// Same seed will produce similar results

428

const operation2 = await client.models.generateVideos({

429

model: 'veo-2.0-generate-001',

430

prompt: 'A sunset over the ocean',

431

config: {

432

seed: 12345,

433

aspectRatio: '16:9',

434

durationSeconds: 5

435

}

436

});

437

```

438

439

### Download Generated Video

440

441

```typescript

442

import * as fs from 'fs';

443

import * as https from 'https';

444

445

// Wait for video generation

446

const completed = await pollVideoOperation(client, operation.name!);

447

448

const videoUri = completed.response?.generatedVideos?.[0]?.video?.uri;

449

450

if (videoUri) {

451

// Download video from URI

452

const downloadVideo = (uri: string, outputPath: string): Promise<void> => {

453

return new Promise((resolve, reject) => {

454

const file = fs.createWriteStream(outputPath);

455

https.get(uri, (response) => {

456

response.pipe(file);

457

file.on('finish', () => {

458

file.close();

459

resolve();

460

});

461

}).on('error', (err) => {

462

fs.unlink(outputPath, () => {});

463

reject(err);

464

});

465

});

466

};

467

468

await downloadVideo(videoUri, './generated_video.mp4');

469

console.log('Video downloaded to ./generated_video.mp4');

470

}

471

```

472

473

### Advanced Configuration

474

475

```typescript

476

const operation = await client.models.generateVideos({

477

model: 'veo-2.0-generate-001',

478

prompt: 'A bustling street market with colorful stalls and people',

479

config: {

480

// Video settings

481

aspectRatio: '16:9',

482

durationSeconds: 10,

483

frameRate: 30,

484

485

// Quality and style

486

guidanceScale: 8.0,

487

negativePrompt: 'static, boring, low quality, artifacts',

488

489

// Safety

490

safetyFilterLevel: SafetyFilterLevel.BLOCK_MEDIUM_AND_ABOVE,

491

includeRaiReason: true,

492

493

// Generation

494

numberOfVideos: 2,

495

seed: 42,

496

497

// Output

498

outputVideoType: 'video/mp4'

499

}

500

});

501

```

502

503

### Error Handling and Retry Logic

504

505

```typescript

506

async function generateVideoWithRetry(

507

client: GoogleGenAI,

508

params: GenerateVideosParameters,

509

maxRetries: number = 3

510

): Promise<GenerateVideosOperation> {

511

let lastError: Error | null = null;

512

513

for (let attempt = 1; attempt <= maxRetries; attempt++) {

514

try {

515

console.log(`Attempt ${attempt}/${maxRetries}`);

516

517

const operation = await client.models.generateVideos(params);

518

const completed = await pollVideoOperation(client, operation.name!);

519

520

if (completed.error) {

521

throw new Error(`Operation failed: ${completed.error.message}`);

522

}

523

524

if (completed.response?.generatedVideos?.[0]?.video?.uri) {

525

console.log('Video generation successful');

526

return completed;

527

}

528

529

throw new Error('No video generated');

530

} catch (error) {

531

lastError = error as Error;

532

console.error(`Attempt ${attempt} failed:`, error);

533

534

if (attempt < maxRetries) {

535

const backoffMs = Math.pow(2, attempt) * 1000;

536

console.log(`Retrying in ${backoffMs}ms...`);

537

await new Promise(resolve => setTimeout(resolve, backoffMs));

538

}

539

}

540

}

541

542

throw lastError || new Error('Max retries exceeded');

543

}

544

545

// Use with retry logic

546

try {

547

const result = await generateVideoWithRetry(client, {

548

model: 'veo-2.0-generate-001',

549

prompt: 'A peaceful forest scene',

550

config: {

551

aspectRatio: '16:9',

552

durationSeconds: 5

553

}

554

});

555

556

console.log('Final video:', result.response?.generatedVideos?.[0]?.video?.uri);

557

} catch (error) {

558

console.error('Video generation failed after retries:', error);

559

}

560

```

561

562

### Monitoring Multiple Operations

563

564

```typescript

565

// Start multiple video generations

566

const operations = await Promise.all([

567

client.models.generateVideos({

568

model: 'veo-2.0-generate-001',

569

prompt: 'A sunrise over mountains'

570

}),

571

client.models.generateVideos({

572

model: 'veo-2.0-generate-001',

573

prompt: 'A waterfall in a tropical forest'

574

}),

575

client.models.generateVideos({

576

model: 'veo-2.0-generate-001',

577

prompt: 'City traffic at night'

578

})

579

]);

580

581

console.log(`Started ${operations.length} video generation operations`);

582

583

// Poll all operations

584

const results = await Promise.all(

585

operations.map(op => pollVideoOperation(client, op.name!))

586

);

587

588

// Process results

589

results.forEach((result, index) => {

590

if (result.response?.generatedVideos?.[0]?.video?.uri) {

591

console.log(`Video ${index + 1}: ${result.response.generatedVideos[0].video.uri}`);

592

} else {

593

console.log(`Video ${index + 1}: Failed`);

594

}

595

});

596

```

597

598

### Using Files Module for Large Videos

599

600

```typescript

601

// For video-to-video with large source files, upload first

602

const uploadedVideo = await client.files.upload({

603

file: './large_video.mp4',

604

mimeType: 'video/mp4'

605

});

606

607

// Wait for processing

608

while (uploadedVideo.state === FileState.PROCESSING) {

609

await new Promise(resolve => setTimeout(resolve, 5000));

610

const file = await client.files.get({ file: uploadedVideo.name! });

611

if (file.state === FileState.ACTIVE) {

612

break;

613

}

614

}

615

616

// Use uploaded video URI

617

const operation = await client.models.generateVideos({

618

model: 'veo-2.0-generate-001',

619

prompt: 'Add dramatic music visualization effects',

620

source: {

621

videoUri: uploadedVideo.uri

622

},

623

config: {

624

durationSeconds: 15

625

}

626

});

627

```

628