### Quick Start Product Demo Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Basic implementation showing how to start a timeline, display a banner, and narrate actions. ```ts import { test, expect, showBanner } from "playwright-marketing-videos"; test("product demo", async ({ page, timeline }) => { // Setup — not recorded await page.goto("https://your-app.com"); // Start recording await timeline.start(); // Show a title banner with fade-in/out await showBanner(page, { text: "My Awesome Feature", duration: 3000 }); // Narrate — audio is synced to video segments automatically await timeline.playAudio({ text: "Let me show you this awesome feature." }); // All interactions are now automatically animated: // - Mouse moves in smooth bezier curves // - Clicks show ripple effects // - Typing is character-by-character with realistic timing await page.getByRole("button", { name: "Get Started" }).click(); await page.getByLabel("Email").fill("user@example.com"); }); ``` -------------------------------- ### Basic Test Setup with Timeline Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Use the extended test fixture for automatic marketing animations. Start recording with `timeline.start()` and add voice-over narration with `timeline.playAudio()`. Interactions like clicks and typing are automatically animated. ```typescript import { test, expect, showBanner } from "playwright-marketing-videos"; test("product demo", async ({ page, timeline }) => { // Setup phase — not recorded await page.goto("https://your-app.com/setup"); await seedTestData(page); // Start recording when ready await timeline.start(); // Show a title banner with fade-in/out await showBanner(page, { text: "My Awesome Feature", duration: 3000 }); // Add voice-over narration — synced to video automatically await timeline.playAudio({ text: "Let me show you this awesome feature." }); // All interactions are automatically animated: // - Mouse moves in smooth bezier curves // - Clicks show ripple effects // - Typing is character-by-character with realistic timing await page.getByRole("button", { name: "Get Started" }).click(); await page.getByLabel("Email").fill("user@example.com"); }); // → marketing-videos/product-demo.mp4 is composed automatically ``` -------------------------------- ### Install Playwright Marketing Videos Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Install the library using npm. ```bash npm install playwright-marketing-videos ``` -------------------------------- ### Full Product Demo with Voice-Over Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Comprehensive example demonstrating banners, narration, and element highlighting. ```ts import { test, showBanner, highlightElement, } from "playwright-marketing-videos"; test("full product demo", async ({ page, timeline }) => { // Setup — not recorded await page.goto("https://acme.example.com"); // Start recording await timeline.start(); await showBanner(page, { text: "Acme — Project Management", duration: 4000 }); await timeline.playAudio({ text: "Welcome to Acme — the fastest way to manage your projects." }); await page.waitForLoadState("networkidle"); await timeline.playAudio({ text: "Let me show you how easy it is to create a new project." }); await page.getByRole("button", { name: "New Project" }).click(); await page.getByLabel("Project name").fill("My First Project"); // Highlight a key feature await highlightElement(page, page.locator(".template-picker"), { borderColor: "#4f46e5", zoomScale: 1.08 }); await timeline.playAudio({ text: "Choose from dozens of pre-built templates to get started instantly." }); await page.getByRole("button", { name: "Create" }).click(); }); ``` -------------------------------- ### Install ElevenLabs Package and Set API Key Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Install the ElevenLabs package and set your API key as an environment variable. This is necessary for using the ElevenLabs text-to-speech provider. ```bash npm install @elevenlabs/elevenlabs-js export ELEVENLABS_API_KEY="your-api-key-here" ``` -------------------------------- ### Basic Timeline Recording Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Start timeline recording manually after setup. The output file is derived from the test title and placed in the marketing-videos/ directory. ```typescript import { test } from "playwright-marketing-videos"; test("product demo", async ({ page, timeline }) => { // Setup phase — not recorded await page.goto("https://app.example.com/setup"); await createDemoUser(page); // Start recording await timeline.start(); await page.goto("https://app.example.com"); await page.getByRole("button", { name: "New Project" }).click(); await page.getByLabel("Name").fill("My Project"); }); // → marketing-videos/product-demo.mp4 is composed automatically ``` -------------------------------- ### Install Kokoro Package Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Install the Kokoro package using npm. This package provides text-to-speech functionality. ```bash npm install kokoro-js ``` -------------------------------- ### Configure Playwright for Marketing Videos Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Setup a dedicated configuration file for high-resolution video output. ```ts // playwright.marketing.config.ts import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ testMatch: "**/*.marketing-video.ts", use: { ...devices["Desktop Chrome"], viewport: { width: 1920, height: 1080 }, screenshot: "off", locale: "en-US" }, timeout: 120_000, outputDir: "marketing-videos" }); ``` -------------------------------- ### showChapter(page, title, options) Example Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Show a chapter overlay with a blurred backdrop for section titles in marketing videos. Customize the description and duration. This uses Playwright v1.59's built-in screencast API. ```typescript import { test, showChapter } from "playwright-marketing-videos"; test("chapter demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); await showChapter(page, "Chapter 1: Getting Started", { description: "Setting up your first project", duration: 3000 // default: 2000ms }); // Continue with demo content... await page.getByRole("button", { name: "Create Project" }).click(); await showChapter(page, "Chapter 2: Advanced Features", { description: "Unlock the full potential", duration: 2500 }); }); ``` -------------------------------- ### Implement Custom Video Provider Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Extend the `VideoProvider` interface to integrate with external video generation APIs. This example demonstrates creating a custom provider that calls a hypothetical video generation API. ```typescript import { test, generateVideoOverlay, playVideoOverlay, type VideoProvider } from "playwright-marketing-videos"; // Custom provider implementation class MyCustomProvider implements VideoProvider { readonly name = "my-provider"; async generate(options: { prompt: string; durationSec: number; aspectRatio: string; cacheDir?: string; cacheKey?: string; }): Promise { // Call your preferred video generation API const response = await fetch("https://my-video-api.com/generate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ prompt: options.prompt, duration: options.durationSec, aspect: options.aspectRatio }) }); if (!response.ok) { throw new Error(`API error: ${response.status}`); } return Buffer.from(await response.arrayBuffer()); } } test("custom provider demo", async ({ page, timeline }) => { const video = await generateVideoOverlay({ prompt: "An abstract gradient animation", durationSec: 5, provider: new MyCustomProvider() }); await page.goto("https://your-app.com"); await timeline.start(); await playVideoOverlay(page, video); }); ``` -------------------------------- ### Kokoro (Default TTS Provider) Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Installs and uses the Kokoro package for text-to-speech. No API key is needed for the default free and local provider. The first call downloads a model, which is then cached. ```APIDOC ## Install Kokoro ```bash npm install kokoro-js ``` ## Play Audio with Kokoro ```ts // Default provider — no API key needed! // First call downloads an ~86MB model (cached after that) await timeline.playAudio({ text: "Welcome to our product demo!", voice: "af_sky", // Optional (default: "af_heart") }); ``` ### Available Options - `voice` — Kokoro voice ID (default: `"af_heart"`) - `dtype` — Model precision: `"fp32"`, `"q8"`, `"q4"` (default: `"q8"`) - `modelId` — HuggingFace model ID (default: `"onnx-community/Kokoro-82M-v1.0-ONNX"`) ``` -------------------------------- ### showBanner(page, options) Example Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Display a full-screen banner overlay with customizable animations, colors, text styling, and an optional logo. The banner can persist across page navigations if a callback is provided. ```typescript import { test, showBanner } from "playwright-marketing-videos"; test("banner showcase", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); // Basic banner with default styling await showBanner(page, { text: "Welcome to Our Product", duration: 3000 }); // Customized banner with logo and callback for navigation await showBanner(page, { text: "Feature Showcase", duration: 4000, fadeInMs: 500, fadeOutMs: 500, backgroundColor: "#1e212b", textColor: "#ffffff", fontSize: "48px", logoUrl: "https://cdn.example.com/logo.png", logoText: "Acme Inc", callback: async () => { // Banner persists while navigating await page.goto("https://your-app.com/features"); } }); }); ``` -------------------------------- ### Screencast Control API Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Methods for starting and stopping high-resolution video recording. ```APIDOC ## startScreencast(page, options?) ### Description Start high-resolution video recording. ### Parameters #### Request Body - **path** (string) - Optional - Output file path - **size** (object) - Optional - Width and height dimensions - **quality** (number) - Optional - Recording quality (0-100) ## stopScreencast(page) ### Description Stop recording and finalize the video file. ``` -------------------------------- ### ElevenLabs TTS Provider Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Installs and configures the ElevenLabs package for text-to-speech. Requires an API key to be set as an environment variable. ```APIDOC ## Install ElevenLabs ```bash npm install @elevenlabs/elevenlabs-js export ELEVENLABS_API_KEY="your-api-key-here" ``` ## Play Audio with ElevenLabs ```ts await timeline.playAudio({ provider: "elevenlabs", text: "Welcome to our product demo!", voiceId: "21m00Tcm4TlvDq8ikWAM", modelId: "eleven_multilingual_v2" // Optional (this is the default) }); ``` Get an API key at [elevenlabs.io](https://elevenlabs.io). ``` -------------------------------- ### Start and Stop Screencast Recording Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Initiate and terminate high-resolution video recording using Playwright's screencast API. Configure output path, resolution, and quality. The recording object can be disposed to stop. ```typescript const recording = await startScreencast(page, { path: "output/demo.webm", size: { width: 1920, height: 1080 }, quality: 90, }); // ... perform actions ... await recording.dispose(); // or: await stopScreencast(page); ``` -------------------------------- ### Implement Scroll Animations Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Display a visual indicator during scroll operations to provide better feedback. This example shows how to hide the cursor, display the scroll animation, perform a scroll, and then hide the animation while restoring the cursor. ```typescript import { test, showScrollAnimation, hideScrollAnimation, hideCursor, showCursor } from "playwright-marketing-videos"; test("scroll demo", async ({ page, timeline }) => { await page.goto("https://your-app.com/long-page"); await timeline.start(); await timeline.playAudio({ text: "Let me scroll down to show you more." }); // Show scroll indicator and hide cursor await hideCursor(page); await showScrollAnimation(page); await page.waitForTimeout(400); // Perform the scroll await page.evaluate(() => { window.scrollTo({ top: 1000, behavior: "smooth" }); }); await page.waitForTimeout(1000); // Remove scroll indicator and restore cursor await hideScrollAnimation(page); await showCursor(page); // Continue with interactions await page.getByRole("button", { name: "Learn More" }).click(); }); ``` -------------------------------- ### Manually Compose Timeline Segments Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Compose all recorded segments and audio into a final MP4 file using ffmpeg. This is an alternative to the automatic composition that occurs at the end of a test. Requires ffmpeg and ffprobe to be installed and available on the system's PATH. ```typescript import { test, Timeline } from "playwright-marketing-videos"; test("manual composition", async ({ page }) => { const timeline = new Timeline({ page, outputDir: "./timeline-segments", size: { width: 1920, height: 1080 } }); await page.goto("https://your-app.com"); await timeline.start(); await timeline.playAudio({ text: "Recording segment one." }); await page.getByRole("button", { name: "Action 1" }).click(); await timeline.playAudio({ text: "Recording segment two." }); await page.getByRole("button", { name: "Action 2" }).click(); await timeline.stop(); // Get segment information const segments = timeline.getSegments(); console.log(`Recorded ${segments.length} segments`); // Write manifest for debugging await timeline.writeManifest("./output/demo.mp4"); // Compose final video (requires ffmpeg and ffprobe on PATH) const outputPath = await timeline.compose("./output/demo.mp4"); console.log(`Video ready: ${outputPath}`); }); ``` -------------------------------- ### Create a Quick Product Intro Screencast Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Demonstrates the basic usage of the timeline fixture to record interactions and add voice-over narration. The timeline handles segment recording and post-production audio syncing. ```ts import { test, showBanner } from "playwright-marketing-videos"; test("quick product intro", async ({ page, timeline }) => { // Setup — not recorded await page.goto("https://your-app.com"); // Start recording await timeline.start(); // Show a banner with voice-over await showBanner(page, { text: "Acme — Ship Faster", duration: 3000 }); await timeline.playAudio({ text: "Welcome to Acme — the fastest way to ship." }); // Interactions are automatically animated (smooth cursor, typing, ripples) await page.getByRole("button", { name: "Get Started" }).click(); await page.getByLabel("Email").fill("user@example.com"); }); // → marketing-videos/quick-product-intro.mp4 ``` -------------------------------- ### Run Marketing Video Tests Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Execute tests using the specific marketing configuration file. ```bash npx playwright test --config playwright.marketing.config.ts ``` -------------------------------- ### Record with Screencast API Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Use startScreencast for granular control over resolution and quality. ```ts import { test, startScreencast, stopScreencast } from "playwright-marketing-videos"; test("my marketing video", async ({ page }) => { const recording = await startScreencast(page, { path: "marketing-videos/demo.webm", size: { width: 1920, height: 1080 }, }); // ... perform actions ... await recording.dispose(); // or: await stopScreencast(page); }); ``` -------------------------------- ### generateVideoOverlay(options) Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Generates AI video clips from text prompts using Runway's Gen-4 Turbo model or loads pre-existing videos from URLs. Results are cached locally. ```APIDOC ## generateVideoOverlay(options) ### Description Generates AI video clips from text prompts using Runway's Gen-4 Turbo model or downloads pre-existing videos from URLs. Results are cached locally. ### Parameters #### Request Body - **prompt** (string) - Required - Text description for AI generation or cache key for URL videos. - **durationSec** (number) - Optional - Duration of the video in seconds. - **aspectRatio** (string) - Optional - Aspect ratio of the video (e.g., "16:9", "9:16"). - **provider** (object) - Optional - Custom provider instance (RunwayVideoProvider or UrlVideoProvider). ### Response - **VideoOverlay** (object) - The generated or loaded video overlay object. ``` -------------------------------- ### Generate and Play Video Overlay with Runway (Default) Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Generate a video overlay from a text prompt using the default Runway provider and then play it on the page. The duration and aspect ratio can be customized. ```ts import { generateVideoOverlay, playVideoOverlay } from "playwright-marketing-videos"; const video = await generateVideoOverlay({ prompt: "A smooth camera fly-through of a modern SaaS dashboard with charts animating in", durationSec: 5, // Video length in seconds (default: 5) aspectRatio: "16:9" // "16:9" (default) or "9:16" for vertical videos }); await playVideoOverlay(page, video); ``` -------------------------------- ### startScreencast(page, options) / stopScreencast(page) Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Manual screencast control for high-resolution recording. ```APIDOC ## startScreencast(page, options) ### Description Manual screencast control using Playwright v1.59's API for high-resolution recording without the Timeline system. ### Parameters - **page** (Page) - Required - The Playwright page instance. - **options** (object) - Required - Configuration object containing path, size (width/height), and quality. ``` -------------------------------- ### Cut Screencast Segment with Playwright Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Cuts the current screencast segment and starts a new one. Use this to create segment boundaries without audio. Supports fade transitions and attaching pre-generated audio to the next segment. ```typescript import { test, showBanner } from "playwright-marketing-videos"; test("segment cuts demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); await showBanner(page, { text: "Part 1: Overview", duration: 2000 }); await page.getByRole("link", { name: "Dashboard" }).click(); // Cut with fade transitions await timeline.cut({ fadeOutMs: 500, fadeInMs: 300 }); await showBanner(page, { text: "Part 2: Features", duration: 2000 }); await page.getByRole("link", { name: "Features" }).click(); // Cut with pre-generated audio attached to next segment const audio = await generateAudioLayer({ text: "Now for the finale." }); await timeline.cut({ audio, fadeInMs: 400 }); await page.getByRole("button", { name: "Finish" }).click(); }); ``` -------------------------------- ### Generate and Play Video Overlays Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Generates AI videos from prompts or downloads existing videos from URLs. Use `generateVideoOverlay` for creation and `playVideoOverlay` to display them. Results are cached locally. Requires RUNWAYML_API_KEY for AI generation. ```typescript import { test, generateVideoOverlay, playVideoOverlay, RunwayVideoProvider, UrlVideoProvider, type VideoOverlay } from "playwright-marketing-videos"; let introVideo: VideoOverlay; let brandVideo: VideoOverlay; test.beforeAll(async () => { // AI-generated video (requires RUNWAYML_API_KEY env var) introVideo = await generateVideoOverlay({ prompt: "Cinematic zoom into a glowing laptop screen showing a dashboard, soft blue light, professional office", durationSec: 5, aspectRatio: "16:9" // or "9:16" for vertical/mobile videos }); // Custom Runway configuration const customVideo = await generateVideoOverlay({ prompt: "Abstract particles forming a logo", provider: new RunwayVideoProvider({ model: "gen4_turbo", apiKey: "rk-custom-api-key" // Override env var }) }); // Pre-existing video from URL (no AI generation) brandVideo = await generateVideoOverlay({ prompt: "Brand intro", // Used for cache key only provider: new UrlVideoProvider("https://cdn.example.com/brand-intro.mp4") }); }); test("video overlay demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); // Play AI video as full-screen overlay await playVideoOverlay(page, introVideo); await timeline.playAudio({ text: "Welcome to the future." }); // Play brand video and continue immediately (don't wait) await playVideoOverlay(page, brandVideo, false); // UI interactions happen while video plays await page.getByRole("button", { name: "Enter" }).click(); }); ``` -------------------------------- ### Use Pre-existing Video from URL as Overlay Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Incorporate a hosted video file as an overlay by providing its URL. This is ideal for brand intros or pre-rendered animations. ```typescript import { test, generateVideoOverlay, playVideoOverlay, showBanner, UrlVideoProvider, type VideoOverlay } from "playwright-marketing-videos"; let brandIntro: VideoOverlay; test.beforeAll(async () => { brandIntro = await generateVideoOverlay({ prompt: "Brand intro video", provider: new UrlVideoProvider("https://cdn.example.com/videos/brand-intro.mp4") }); }); test("branded intro from URL", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); await playVideoOverlay(page, brandIntro); await timeline.playAudio({ text: "Built by developers, for developers." }); // Continue with the live product demo await showBanner(page, { text: "Let's dive in.", duration: 3000 }); await page.getByRole("button", { name: "Get Started" }).click(); }); ``` -------------------------------- ### showActionAnnotations(page, options) Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Enables visual action annotations on the screencast. ```APIDOC ## showActionAnnotations(page, options) ### Description Enables visual action annotations on the screencast. Each Playwright action is labeled on the video recording. ### Parameters - **page** (Page) - Required - The Playwright page instance. - **options** (object) - Required - Configuration including position (e.g., "top-right"), fontSize, and duration. ``` -------------------------------- ### Generate Video Overlay with URL Provider Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Use the `UrlVideoProvider` to generate a video overlay from a pre-existing video file hosted online. The video is downloaded and cached locally. ```ts import { generateVideoOverlay, playVideoOverlay, UrlVideoProvider } from "playwright-marketing-videos"; const video = await generateVideoOverlay({ prompt: "Company brand intro", // Used only for logging/cache key provider: new UrlVideoProvider("https://cdn.example.com/videos/brand-intro.mp4") }); await playVideoOverlay(page, video); ``` -------------------------------- ### AI Video Intro with Voice-Over Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Integrate AI-generated video overlays as cinematic intros. ```ts import { test, generateVideoOverlay, playVideoOverlay, showBanner, type VideoOverlay } from "playwright-marketing-videos"; let introVideo: VideoOverlay; test.beforeAll(async () => { introVideo = await generateVideoOverlay({ prompt: "Cinematic zoom into a glowing laptop screen showing a beautiful dashboard, soft blue light, professional office background", durationSec: 5, aspectRatio: "16:9" }); }); test("video intro demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); await playVideoOverlay(page, introVideo); await timeline.playAudio({ text: "Introducing the next generation of project analytics." }); // Continue with the product demo await showBanner(page, { text: "Real-Time Analytics Dashboard", duration: 3000 }); await page.getByRole("link", { name: "Dashboard" }).click(); }); ``` -------------------------------- ### Runway (Default Video Provider) Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Configures and uses the RunwayML provider for generating AI video clips. Requires an API key and allows customization of models and aspect ratios. ```APIDOC ## Runway (Default Provider) Set your API key: ```bash export RUNWAYML_API_KEY="your-api-key-here" ``` ```ts import { generateVideoOverlay, playVideoOverlay } from "playwright-marketing-videos"; const video = await generateVideoOverlay({ prompt: "A smooth camera fly-through of a modern SaaS dashboard with charts animating in", durationSec: 5, // Video length in seconds (default: 5) aspectRatio: "16:9" // "16:9" (default) or "9:16" for vertical videos }); await playVideoOverlay(page, video); ``` The default Runway provider uses the **Gen-4 Turbo** model. You can customize the model or API key by providing your own `RunwayVideoProvider` instance: ```ts import { generateVideoOverlay, RunwayVideoProvider } from "playwright-marketing-videos"; const video = await generateVideoOverlay({ prompt: "Colorful particles forming a company logo", provider: new RunwayVideoProvider({ model: "gen4_turbo", apiKey: "rk-my-specific-key" // Override the environment variable }) }); ``` Get an API key at [runwayml.com](https://runwayml.com). ``` -------------------------------- ### generateVideoOverlay API Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Generates a short AI video clip from a text prompt. Supports customization of duration, aspect ratio, and the video generation provider. ```APIDOC ### `generateVideoOverlay(options)` Generates a short AI video clip from a text prompt. | Option | Type | Default | Description | |---|---|---|---| | `prompt` | `string` | *required* | Text prompt describing the video to generate | | `durationSec` | `number` | `5` | Video duration in seconds | | `aspectRatio` | `"16:9" | "9:16"` | `"16:9"` | Aspect ratio — use `"9:16"` for vertical/mobile videos | | `provider` | `VideoProvider` | `RunwayVideoProvider` | Video generation provider instance | **Returns:** `VideoOverlay` object with `{ filePath, prompt, durationSec }`. ``` -------------------------------- ### Play Audio with Kokoro (Default Provider) Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Use the default Kokoro provider to play audio from text. The first call downloads a model, which is cached for subsequent uses. An API key is not required for this provider. ```ts // Default provider — no API key needed! // First call downloads an ~86MB model (cached after that) await timeline.playAudio({ text: "Welcome to our product demo!", voice: "af_sky", // Optional (default: "af_heart") }); ``` -------------------------------- ### Implement Custom Video Provider Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Implement the VideoProvider interface to add support for custom video generation APIs. The generate method should return the video file as a Buffer. ```typescript import type { VideoProvider } from "playwright-marketing-videos"; class MyCustomProvider implements VideoProvider { readonly name = "my-provider"; async generate(options: { prompt: string; durationSec: number; aspectRatio: string; cacheDir?: string; cacheKey?: string; }): Promise { // Call your preferred video generation API here // Return the video file as a Buffer const response = await fetch("https://my-video-api.com/generate", { method: "POST", body: JSON.stringify({ prompt: options.prompt, duration: options.durationSec }) }); return Buffer.from(await response.arrayBuffer()); } } const video = await generateVideoOverlay({ prompt: "An abstract gradient animation", provider: new MyCustomProvider() }); ``` -------------------------------- ### Migrate to ElevenLabs Provider in v0.3.x Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md When migrating from v0.2.x to v0.3.x, explicitly add the `provider: "elevenlabs"` option to `generateAudioLayer()` calls if you were previously using ElevenLabs as the default. ```ts // Before (v0.2.x) const audio = await generateAudioLayer({ text: "Hello", voiceId: "..." }); // After (v0.3.x) const audio = await generateAudioLayer({ provider: "elevenlabs", text: "Hello", voiceId: "..." }); ``` -------------------------------- ### Generate Video Overlay with Custom Runway Provider Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Generate a video overlay using a custom `RunwayVideoProvider` instance to specify the model and API key directly, overriding environment variables. ```ts import { generateVideoOverlay, RunwayVideoProvider } from "playwright-marketing-videos"; const video = await generateVideoOverlay({ prompt: "Colorful particles forming a company logo", provider: new RunwayVideoProvider({ model: "gen4_turbo", apiKey: "rk-my-specific-key" // Override the environment variable }) }); ``` -------------------------------- ### generateAudioLayer Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Generates text-to-speech audio files using either Kokoro (free, local) or ElevenLabs (cloud, premium). Results are cached locally to avoid regeneration. ```APIDOC ## generateAudioLayer(options) ### Description Generates text-to-speech audio files using either Kokoro (free, local) or ElevenLabs (cloud, premium). Results are cached locally to avoid regeneration. ### Method `generateAudioLayer` ### Parameters #### Options - **text** (string) - Required - The text to convert to speech. - **provider** (string) - Optional - The audio provider to use. Defaults to 'kokoro'. Can be 'elevenlabs'. - **voice** (string) - Optional - For Kokoro provider, the voice to use. Defaults to 'af_heart'. - **dtype** (string) - Optional - For Kokoro provider, the model precision. Options: 'fp32', 'q8', 'q4'. Defaults to 'q8'. - **voiceId** (string) - Optional - For ElevenLabs provider, the voice ID. - **modelId** (string) - Optional - For ElevenLabs provider, the model ID. Defaults to 'eleven_multilingual_v2'. ### Request Example ```typescript // Kokoro provider (default) const introAudio = await generateAudioLayer({ text: "Welcome to our product demo!", voice: "af_sky", dtype: "q8" }); // ElevenLabs provider const premiumAudio = await generateAudioLayer({ provider: "elevenlabs", text: "Experience the future of productivity.", voiceId: "21m00Tcm4TlvDq8ikWAM", modelId: "eleven_multilingual_v2" }); ``` ### Response Returns an audio layer object that can be used with the timeline. ``` -------------------------------- ### Migration from v0.2.x to v0.3.x Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Provides instructions for migrating from older versions of the library, specifically for users who were previously using ElevenLabs as the default TTS provider. ```APIDOC ### Migrating from v0.2.x If you were using ElevenLabs (the previous default), add `provider: "elevenlabs"` to your `generateAudioLayer()` calls: ```ts // Before (v0.2.x) const audio = await generateAudioLayer({ text: "Hello", voiceId: "..." }); // After (v0.3.x) const audio = await generateAudioLayer({ provider: "elevenlabs", text: "Hello", voiceId: "..." }); ``` ``` -------------------------------- ### Visual Overlay API Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Methods for displaying visual overlays like banners, chapters, and element highlights during the recording process. ```APIDOC ## showBanner(page, title, options?) ### Description Displays a full-screen banner overlay with fade-in/out animations. ### Parameters #### Request Body - **duration** (number) - Optional - Display duration in ms - **fadeInMs** (number) - Optional - Fade-in duration - **fadeOutMs** (number) - Optional - Fade-out duration - **backgroundColor** (string) - Optional - Background color hex - **textColor** (string) - Optional - Text color hex - **fontSize** (string) - Optional - Font size - **callback** (function) - Optional - Async function to run while banner is shown ## highlightElement(page, locator, options?) ### Description Highlights a page element with a zoom-in effect and colored border. ### Parameters #### Request Body - **duration** (number) - Optional - Highlight duration - **borderColor** (string) - Optional - Border color - **borderWidth** (number) - Optional - Border width in px - **zoomScale** (number) - Optional - Zoom factor ``` -------------------------------- ### Chain Multiple AI-Generated Video Overlays Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Create a story arc by sequencing multiple AI-generated video clips. This is useful for presenting a problem and then its solution. ```typescript import { test, generateVideoOverlay, playVideoOverlay, showBanner, type VideoOverlay } from "playwright-marketing-videos"; let problemVideo: VideoOverlay; let solutionVideo: VideoOverlay; test.beforeAll(async () => { problemVideo = await generateVideoOverlay({ prompt: "Frustrated person drowning in spreadsheets and sticky notes, messy desk, overwhelmed expression", durationSec: 5 }); solutionVideo = await generateVideoOverlay({ prompt: "Clean modern workspace with a sleek app on screen, person smiling confidently, minimal design", durationSec: 5 }); }); test("multi-scene video", async ({ page }) => { await page.goto("https://your-app.com"); // Scene 1: Problem statement await playVideoOverlay(page, problemVideo); await showBanner(page, "There's a better way."); // Scene 2: Solution reveal await playVideoOverlay(page, solutionVideo); await showBanner(page, "Meet Acme.", { duration: 3000 }); // Continue with live product demo... await page.getByRole("button", { name: "Get Started" }).click(); }); ``` -------------------------------- ### playVideoOverlay(page, overlay, waitForVideoToFinish) Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Plays a video overlay as a full-screen layer on the page. The video is injected as a base64-encoded element. ```APIDOC ## playVideoOverlay(page, overlay, waitForVideoToFinish) ### Description Plays a video overlay as a full-screen layer on the page. The video is injected as a base64-encoded element that Playwright's native recording captures. ### Parameters - **page** (Page) - Required - The Playwright page instance. - **overlay** (VideoOverlay) - Required - The video overlay object to play. - **waitForVideoToFinish** (boolean) - Optional - Whether to wait for the video to finish before continuing execution (defaults to true). ``` -------------------------------- ### Play Video Overlay with Options Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Plays a video overlay on the page, optionally waiting for it to finish. The video is injected as a base64-encoded element. Use the third argument `true` to explicitly wait. ```typescript import { test, generateVideoOverlay, playVideoOverlay, type VideoOverlay } from "playwright-marketing-videos"; let problemVideo: VideoOverlay; let solutionVideo: VideoOverlay; test.beforeAll(async () => { problemVideo = await generateVideoOverlay({ prompt: "Frustrated person drowning in spreadsheets, messy desk, overwhelmed expression", durationSec: 5 }); solutionVideo = await generateVideoOverlay({ prompt: "Clean workspace with sleek app on screen, person smiling, minimal design", durationSec: 5 }); }); test("problem-solution narrative", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); // Scene 1: Problem (waits for video to finish by default) await playVideoOverlay(page, problemVideo); await timeline.playAudio({ text: "Sound familiar?" }); // Scene 2: Solution await playVideoOverlay(page, solutionVideo, true); // explicit wait await timeline.playAudio({ text: "There's a better way." }); await page.getByRole("button", { name: "Get Started" }).click(); }); ``` -------------------------------- ### Set RunwayML API Key Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Set your RunwayML API key as an environment variable. This is required for the default video generation provider. ```bash export RUNWAYML_API_KEY="your-api-key-here" ``` -------------------------------- ### Use ElevenLabs for Premium Voice-Over Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Integrate ElevenLabs for high-quality, multilingual narration. This requires an API key and specifies voice and model IDs for the desired output. ```typescript import { test, showBanner } from "playwright-marketing-videos"; test("premium voice demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); await showBanner(page, { text: "Productivity Reimagined", duration: 3000 }); await timeline.playAudio({ provider: "elevenlabs", text: "Welcome to the future of productivity. Let us show you what's possible.", voiceId: "21m00Tcm4TlvDq8ikWAM", modelId: "eleven_multilingual_v2" }); await page.getByRole("button", { name: "Start Tour" }).click(); }); ``` -------------------------------- ### Display Full-Screen Banner Overlay Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Show a full-screen banner with customizable fade animations, background, text color, and font size. A callback can be provided to execute actions while the banner is displayed. ```typescript await showBanner(page, "Feature Showcase", { duration: 3000, // Display duration in ms (default: 2000) fadeInMs: 500, // Fade-in duration (default: 300) fadeOutMs: 500, // Fade-out duration (default: 300) backgroundColor: "#1e212b", // Background color (default: "#1e212b") textColor: "#ffffff", // Text color (default: "#ffffff") fontSize: "48px", // Font size (default: "48px") callback: async () => { // Optional: runs while the banner is shown (e.g. navigate to a page) await page.goto("https://your-app.com"); } }); ``` -------------------------------- ### showBanner(page, title, options?) Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Displays a banner overlay on the page during the screencast. ```APIDOC ## showBanner(page, title, options?) ### Description Displays a banner with a title and optional configuration during the video recording. ### Parameters - **page** (Page) - Required - The Playwright page instance. - **title** (string) - Required - The text to display in the banner. - **options** (object) - Optional - Configuration for duration and styling. ``` -------------------------------- ### Playwright Config for Marketing Videos Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Configure Playwright for high-resolution marketing video recording. Set `testMatch` to target marketing video files, specify a high `viewport` resolution, disable screenshots, and set an `outputDir` for the videos. ```typescript // playwright.marketing.config.ts import { defineConfig, devices } from "@playwright/test"; export default defineConfig({ testMatch: "**/*.marketing-video.ts", use: { ...devices["Desktop Chrome"], viewport: { width: 1920, height: 1080 }, screenshot: "off", locale: "en-US" }, timeout: 120_000, outputDir: "marketing-videos" }); // Run with: // npx playwright test --config playwright.marketing.config.ts ``` -------------------------------- ### Play Video Overlay Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Plays a video overlay as a full-screen layer. Use the second argument to control whether to wait for the video to finish. ```typescript await playVideoOverlay(page, video); ``` ```typescript await playVideoOverlay(page, video, false); ``` -------------------------------- ### Custom Video Providers Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Implement the `VideoProvider` interface to add support for other video generation APIs. ```APIDOC ## Custom Video Providers ### Description Implement the `VideoProvider` interface to add support for other video generation APIs (e.g. Kling, Luma, Stability, Pika). ### `VideoProvider` Interface ```ts interface VideoProvider { readonly name: string; generate(options: { prompt: string; durationSec: number; aspectRatio: string; cacheDir?: string; cacheKey?: string; }): Promise; } ``` ### Example Implementation ```ts import type { VideoProvider } from "playwright-marketing-videos"; class MyCustomProvider implements VideoProvider { readonly name = "my-provider"; async generate(options: { prompt: string; durationSec: number; aspectRatio: string; cacheDir?: string; cacheKey?: string; }): Promise { // Call your preferred video generation API here // Return the video file as a Buffer const response = await fetch("https://my-video-api.com/generate", { method: "POST", body: JSON.stringify({ prompt: options.prompt, duration: options.durationSec }) }); return Buffer.from(await response.arrayBuffer()); } } const video = await generateVideoOverlay({ prompt: "An abstract gradient animation", provider: new MyCustomProvider() }); ``` ``` -------------------------------- ### Generate Audio Layer with Playwright Source: https://context7.com/smallstack/playwright-marketing-videos/llms.txt Generates text-to-speech audio files using Kokoro (default) or ElevenLabs. Results are cached locally. Kokoro is free and local, while ElevenLabs requires an API key. ```typescript import { test, generateAudioLayer } from "playwright-marketing-videos"; test("audio generation demo", async ({ page, timeline }) => { await page.goto("https://your-app.com"); await timeline.start(); // Kokoro provider (default) — free, no API key needed // First call downloads ~86MB model, cached after that const introAudio = await generateAudioLayer({ text: "Welcome to our product demo!", voice: "af_sky", // Optional (default: "af_heart") dtype: "q8" // Model precision: "fp32", "q8", "q4" (default: "q8") }); // ElevenLabs provider — requires ELEVENLABS_API_KEY env var const premiumAudio = await generateAudioLayer({ provider: "elevenlabs", text: "Experience the future of productivity.", voiceId: "21m00Tcm4TlvDq8ikWAM", modelId: "eleven_multilingual_v2" // Optional (default) }); // Use with timeline await timeline.playAudio(introAudio); await page.getByRole("button", { name: "Get Started" }).click(); }); ``` -------------------------------- ### Classic Video Configuration Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Alternative configuration using the standard Playwright video mode. ```ts use: { viewport: { width: 1920, height: 1080 }, video: { mode: "on", size: { width: 1920, height: 1080 } }, }, ``` -------------------------------- ### Show Chapter Overlay Source: https://github.com/smallstack/playwright-marketing-videos/blob/main/README.md Display a chapter overlay with a blurred backdrop, suitable for section titles. This utilizes Playwright's `screencast.showChapter()` API. ```typescript await showChapter(page, "Chapter 1: Getting Started", { description: "Setting up the project", duration: 3000, // default: 2000ms }); ```