{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Generate videos with AI\n", "\n", "Create videos from text prompts or animate images using Google's Veo model." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Problem\n", "\n", "You need to generate video content programmatically—for social media, product demos, or creative applications.\n", "\n", "| Use case | Input | Output |\n", "|----------|-------|--------|\n", "| Social content | Text prompt | Short video clips |\n", "| Product demos | Product image | Animated product video |\n", "| Creative apps | User prompts | Generated video content |\n", "| Marketing | Static images | Animated banners |" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Solution\n", "\n", "**What's in this recipe:**\n", "\n", "- Generate videos from text prompts\n", "- Animate existing images into videos\n", "- Store prompts and generated videos together\n", "\n", "Use Google's Veo model to generate videos. Videos are cached—regeneration only happens if the prompt changes." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Setup" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pip install -qU pixeltable google-genai" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import getpass\n", "import os\n", "\n", "if 'GEMINI_API_KEY' not in os.environ:\n", " os.environ['GEMINI_API_KEY'] = getpass.getpass(\n", " 'Google AI Studio API Key: '\n", " )" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import pixeltable as pxt\n", "from pixeltable.functions import gemini" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata\n", "Created directory 'video_gen_demo'.\n" ] }, { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a fresh directory\n", "pxt.drop_dir('video_gen_demo', force=True)\n", "pxt.create_dir('video_gen_demo')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Generate videos from text prompts" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created table 'text_to_video'.\n", "Added 0 column values with 0 errors.\n" ] }, { "data": { "text/plain": [ "No rows affected." ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a table for text-to-video generation\n", "videos = pxt.create_table(\n", " 'video_gen_demo/text_to_video', {'prompt': pxt.String}\n", ")\n", "\n", "# Add computed column that generates videos\n", "videos.add_computed_column(\n", " video=gemini.generate_videos(\n", " videos.prompt, model='veo-2.0-generate-001'\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Inserting rows into `text_to_video`: 1 rows [00:00, 190.68 rows/s]\n", "Inserted 1 row with 0 errors.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
promptvideo
A serene mountain lake at sunrise with mist rising from the water
\n", " \n", "
" ], "text/plain": [ " prompt \\\n", "0 A serene mountain lake at sunrise with mist ri... \n", "\n", " video \n", "0 /Users/pjlb/.pixeltable/media/066dc2f5cb50475d... " ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Generate a video from a text prompt\n", "videos.insert(\n", " [\n", " {\n", " 'prompt': 'A serene mountain lake at sunrise with mist rising from the water'\n", " }\n", " ]\n", ")\n", "\n", "# View the result\n", "videos.select(videos.prompt, videos.video).collect()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Animate images into videos" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created table 'image_to_video'.\n", "Added 0 column values with 0 errors.\n" ] }, { "data": { "text/plain": [ "No rows affected." ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Create a table for image-to-video generation\n", "animated = pxt.create_table(\n", " 'video_gen_demo/image_to_video',\n", " {'image': pxt.Image, 'description': pxt.String},\n", ")\n", "\n", "# Add computed column that animates images\n", "animated.add_computed_column(\n", " video=gemini.generate_videos(\n", " image=animated.image, model='veo-2.0-generate-001'\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Inserting rows into `image_to_video`: 1 rows [00:00, 291.88 rows/s]\n", "Inserted 1 row with 0 errors.\n" ] }, { "data": { "text/html": [ "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
imagevideo
\n", " \n", "
\n", " \n", "
" ], "text/plain": [ " image \\\n", "0