Skip to content

LooK API Reference

Base URL: http://localhost:3847 (or your deployed URL)

Authentication

Local Development

No authentication is required for local development.

API Keys

When using AI features, include your API keys in request headers:

X-OpenAI-Key: sk-your-openai-key
X-Groq-Key: gsk-your-groq-key

Example:

curl -X POST http://localhost:3847/api/analyze \
  -H "Content-Type: application/json" \
  -H "X-OpenAI-Key: sk-your-key" \
  -d '{"url": "https://example.com"}'

Web Editor

The web editor stores API keys in browser localStorage and automatically includes them in requests. Configure keys via Settings → API Keys.

Environment Variables

Alternatively, set API keys as environment variables on the server:

export OPENAI_API_KEY=sk-your-key
export GROQ_API_KEY=gsk-your-key
look serve

Production

For production deployments, configure your own auth middleware and secure API key handling.

Endpoints

Health Check

GET /api/health

Response:

{
  "status": "ok",
  "version": "2.0.0",
  "openai": true,
  "groq": false,
  "playwright": true
}

Projects

List Projects

GET /api/projects

Get Project

GET /api/project/:id

Delete Project

DELETE /api/project/:id

Analysis & Recording

Analyze URL

POST /api/analyze
Content-Type: application/json

{
  "url": "https://example.com",
  "duration": 25,
  "style": "professional"
}

Start Recording

POST /api/record
Content-Type: application/json

{
  "projectId": "uuid",
  "options": {
    "width": 1920,
    "height": 1080
  }
}

Import

Import Project

POST /api/import
Content-Type: application/json

{
  "url": "https://github.com/user/repo",
  "type": "auto",
  "options": {
    "shallow": true,
    "analyzeReadme": true
  }
}

Get Import Status

GET /api/import/:projectId/status

Live Recording

Start Live Session

POST /api/live/start
Content-Type: application/json

{
  "url": "https://example.com",
  "options": {
    "width": 1920,
    "height": 1080,
    "previewFps": 15
  }
}

Control Live Session

POST /api/live/:sessionId/pause
POST /api/live/:sessionId/resume
POST /api/live/:sessionId/stop

Rendering

Render Final Video

POST /api/render
Content-Type: application/json

{
  "projectId": "uuid",
  "preset": "youtube"
}

Download Video

GET /api/download/:projectId

WebSocket Events

Connect to ws://localhost:3847 for real-time updates.

Client → Server

{ "action": "subscribe", "payload": { "projectId": "uuid" } }
{ "action": "subscribe-live", "payload": { "sessionId": "live-xxx" } }

Server → Client

{ "type": "status", "data": { "stage": "recording", "progress": 50 } }
{ "type": "live-frame", "data": "base64-image-data" }
{ "type": "error", "data": { "message": "Error description" } }

API Documentation

LooK can be used programmatically in your Node.js applications.

Installation

npm install look-demo

Quick Start

import { generateDemo, generateDemoV2, generateMobileDemo } from 'look-demo';

// Generate a demo video
await generateDemo('https://myapp.com', {
  output: './demo.mp4',
  duration: 30,
  voice: 'nova'
});

Core Functions

generateDemo(url, options)

Generate a polished website demo video with AI analysis.

import { generateDemo } from 'look-demo';

const result = await generateDemo('https://stripe.com', {
  // Output settings
  output: './output/demo.mp4',
  duration: 25,                    // seconds
  width: 1920,
  height: 1080,

  // AI settings
  voice: 'nova',                   // nova, alloy, echo, fable, onyx, shimmer
  style: 'professional',           // professional, casual, energetic
  skipVoice: false,
  skipAnalysis: false,

  // Export preset
  preset: 'youtube',               // youtube, twitter, instagram, tiktok, gif

  // Zoom settings
  zoomMode: 'smart',               // none, basic, smart, follow
  followIntensity: 0.5,            // 0-1, for follow mode
  maxZoom: 2.0,
  minZoom: 1.0,
  zoomOnClicks: true,
  zoomOnHover: true,
  zoomSpeed: 'medium',             // slow, medium, fast

  // Cursor settings
  cursorStyle: 'default',          // default, arrow-modern, pointer, dot, circle, crosshair, spotlight, none
  cursorSize: 32,
  cursorColor: '#000000',
  cursorPreset: null,              // light, dark, blue, github, figma, notion, etc.
  cursorGlow: false,

  // Click effects
  clickEffect: 'ripple',           // ripple, pulse, ring, spotlight, none
  clickEffectColor: '#3B82F6',
  clickEffectSize: 60,
  clickEffectDuration: 400,        // ms

  // Preview only
  dryRun: false
});

console.log('Video created:', result.output);

generateDemoV2(url, options)

Use the V2 engine for more reliable recording. Same options as generateDemo.

import { generateDemoV2 } from 'look-demo';

await generateDemoV2('https://myapp.com', {
  output: './demo.mp4',
  duration: 30
});

generateMobileDemo(app, options)

Generate mobile app demos using Appium.

import { generateMobileDemo } from 'look-demo';

await generateMobileDemo('./MyApp.app', {
  // Output settings
  output: './mobile-demo.mp4',
  duration: 25,

  // Platform settings
  platform: 'ios',                 // ios, android
  device: 'iPhone 15 Pro',
  orientation: 'portrait',         // portrait, landscape

  // Touch effects
  touchIndicator: 'circle',        // circle, finger, ripple, dot
  touchColor: 'rgba(255,255,255,0.8)',
  touchSize: 80,
  showSwipeTrail: true,

  // Device frame
  addDeviceFrame: true,
  frameStyle: 'modern',            // modern, minimal

  // AI settings
  voice: 'nova',
  style: 'professional',
  skipVoice: false,

  // Actions script
  actionsScript: './actions.json',

  dryRun: false
});

Project Management

Project Class

Manage saved projects programmatically.

import { Project } from 'look-demo';

// List all projects
const projects = await Project.list();
console.log(projects);

// Load a specific project
const project = await Project.load('abc12345');
console.log(project.name, project.url);

// Create a new project
const newProject = await Project.create({
  name: 'My Demo',
  url: 'https://myapp.com'
});
console.log('Created:', newProject.id);

// Update project
project.name = 'Updated Name';
await project.save();

// Delete project
await project.delete();

Individual Components

AI Analysis

import { analyzeWebsite, generateScript, generateVoiceover } from 'look-demo/v2/ai';

// Analyze a website screenshot
const analysis = await analyzeWebsite(screenshotBase64, {
  title: 'My App',
  description: 'A cool app',
  url: 'https://myapp.com'
});

console.log(analysis.name);        // Detected product name
console.log(analysis.tagline);     // Detected tagline
console.log(analysis.features);    // Key features
console.log(analysis.cta);         // Call to action

// Generate voiceover script
const script = await generateScript(analysis, {
  duration: 25,
  style: 'professional'
});

// Generate audio
const audioPath = await generateVoiceover(script, {
  voice: 'nova'
});

Auto Zoom

import { AutoZoom } from 'look-demo/v2/auto-zoom';

const autoZoom = new AutoZoom({
  minZoom: 1.0,
  maxZoom: 2.0,
  defaultZoom: 1.3,
  zoomDuration: 800,       // ms
  holdDuration: 1500,      // ms
  zoomMode: 'smart',       // none, basic, smart, follow
  followIntensity: 0.5,
  deadzone: 0.2
});

// Generate zoom keyframes from cursor data
const keyframes = autoZoom.generateFromCursor(cursorData, 1920, 1080);

// For follow-cam mode
const followKeyframes = autoZoom.generateFollowZoom(cursorData, 1920, 1080, {
  followIntensity: 0.7
});

Cursor Rendering

import { CursorRenderer, getCursorPreset } from 'look-demo/v2/cursor-renderer';

// Get a preset
const preset = getCursorPreset('github');
// { color: '#24292f', outlineColor: '#ffffff', ... }

const cursor = new CursorRenderer({
  style: 'arrow-modern',   // default, arrow-modern, pointer, dot, circle, crosshair, spotlight
  size: 32,
  color: '#000000',
  outlineColor: '#ffffff',
  shadowBlur: 6,
  glow: true,
  glowIntensity: 0.5,
  trail: false,
  trailLength: 5
});

// Generate cursor image
const cursorPath = await cursor.generateCursorImage('./temp');
const clickCursorPath = await cursor.generateCursorImage('./temp', true);

Click Effects

import { ClickEffectRenderer } from 'look-demo/v2/click-effects';

const clickEffect = new ClickEffectRenderer({
  effect: 'ripple',        // ripple, pulse, ring, spotlight
  color: '#3B82F6',
  size: 60,
  duration: 400,           // ms
  opacity: 0.6
});

// Generate FFmpeg filter for click effects
const clicks = [
  { x: 500, y: 300, t: 1000 },
  { x: 800, y: 450, t: 3500 }
];
const filter = clickEffect.generateSimpleFilter(clicks, 60);

Post Processing

import { postProcess, combineVideoAudio, exportWithPreset } from 'look-demo/v2/post-process';

// Apply post-processing effects
await postProcess(inputPath, outputPath, {
  colorGrade: true,
  vignette: true,
  motionBlur: false
});

// Combine video with audio
await combineVideoAudio(videoPath, audioPath, outputPath);

// Export with preset
await exportWithPreset(inputPath, outputPath, 'twitter');

Server API

The web editor exposes a REST API.

Starting the Server

import { startServer } from 'look-demo/v2/server';

const { url, port } = await startServer({
  port: 3847,
  openBrowser: false
});

console.log(`Server running at ${url}`);

REST Endpoints

Projects

GET /api/projects
List all projects.

GET /api/projects/:id
Get project details.

POST /api/projects
Content-Type: application/json

{
  "name": "My Demo",
  "url": "https://myapp.com"
}
Create a new project.

PUT /api/projects/:id
Content-Type: application/json

{
  "name": "Updated Name"
}
Update a project.

DELETE /api/projects/:id
Delete a project.

Rendering

POST /api/render
Content-Type: application/json

{
  "projectId": "abc12345",
  "options": {
    "preset": "youtube",
    "quality": "high"
  }
}
Start a render job.

GET /api/render/:jobId/status
Check render status.

GET /api/render/:jobId/download
Download rendered video.

Error Handling

import { generateDemo } from 'look-demo';

try {
  await generateDemo('https://myapp.com', options);
} catch (error) {
  if (error.message.includes('FFmpeg')) {
    console.error('FFmpeg not installed');
  } else if (error.message.includes('OpenAI')) {
    console.error('OpenAI API error:', error.message);
  } else if (error.message.includes('Playwright')) {
    console.error('Browser error:', error.message);
  } else {
    console.error('Error:', error.message);
  }
}

TypeScript Support

LooK includes TypeScript definitions:

import { 
  generateDemo, 
  GenerateDemoOptions,
  Project,
  AutoZoom,
  CursorRenderer 
} from 'look-demo';

const options: GenerateDemoOptions = {
  output: './demo.mp4',
  duration: 30,
  voice: 'nova',
  zoomMode: 'smart'
};

await generateDemo('https://myapp.com', options);

Examples

See the examples/ directory for complete examples:


Enterprise Modules

IntelligentOrchestrator

Full AI-powered demo generation with quality scoring:

import { IntelligentOrchestrator } from 'look-demo/v2';

const orchestrator = new IntelligentOrchestrator({
  style: 'professional',
  autoOptimize: true,
  qualityThreshold: 75,
  storyArc: 'auto'
});

const result = await orchestrator.createDemo('https://myapp.com', {
  duration: 30,
  voice: 'nova'
});

console.log(`Quality: ${result.qualityScore.overall} (${result.qualityScore.grade})`);

GifExporter

Convert videos to optimized GIFs:

import { GifExporter, GifQuality } from 'look-demo/v2';

const exporter = new GifExporter({
  width: 640,
  fps: 15,
  quality: GifQuality.MEDIUM
});

await exporter.export('video.mp4', 'output.gif', {
  startTime: 5,
  endTime: 15
});

AutoThumbnailGenerator

Generate thumbnails with AI frame selection:

import { AutoThumbnailGenerator } from 'look-demo/v2';

const generator = new AutoThumbnailGenerator({ sampleCount: 20 });
const analysis = await generator.analyzeVideo('video.mp4');

await generator.generate('video.mp4', 'thumbnail.png', {
  timestamp: analysis.bestTimestamp,
  preset: 'youtube',
  title: 'My Product Demo'
});

AnimatedCaptionsRenderer

Add animated subtitles:

import { AnimatedCaptionsRenderer, CaptionStyle } from 'look-demo/v2';

const captions = new AnimatedCaptionsRenderer({
  style: CaptionStyle.KARAOKE,
  position: 'bottom',
  fontSize: 48
});

const subtitles = captions.parseSRT(srtContent);
await captions.applyToVideo('input.mp4', 'output.mp4', subtitles);

LowerThirdsRenderer

Professional name/title overlays:

import { LowerThirdsRenderer, LowerThirdsStyle } from 'look-demo/v2';

const lowerThird = new LowerThirdsRenderer({
  name: 'John Smith',
  title: 'Product Designer',
  style: LowerThirdsStyle.MODERN
});

lowerThird.setDisplayTime(2, 7);
await lowerThird.applyToVideo('input.mp4', 'output.mp4');

SpotlightRenderer

Focus attention on elements:

import { SpotlightRenderer, SpotlightShape } from 'look-demo/v2';

const spotlight = new SpotlightRenderer({
  overlayOpacity: 0.7,
  shape: SpotlightShape.ROUNDED_RECT
});

spotlight.addSpotlight({
  x: 500, y: 400,
  width: 200, height: 50,
  startTime: 5, endTime: 10
});

SceneTransitionRenderer

Professional scene transitions:

import { SceneTransitionRenderer, TransitionType } from 'look-demo/v2';

const transitions = new SceneTransitionRenderer({
  type: TransitionType.BLUR,
  duration: 0.5
});

await transitions.joinWithTransitions(
  ['clip1.mp4', 'clip2.mp4', 'clip3.mp4'],
  'output.mp4'
);

WatermarkGenerator

Add text or logo watermarks:

import { WatermarkGenerator } from 'look-demo/v2';

const watermark = new WatermarkGenerator({
  type: 'text',
  text: 'MyCompany',
  position: 'bottom-right',
  opacity: 0.7
});

await watermark.apply('input.mp4', 'output.mp4');

IntroOutroGenerator

Create branded intro/outro cards:

import { IntroOutroGenerator } from 'look-demo/v2';

const generator = new IntroOutroGenerator({
  theme: 'gradient',
  brandColor: '#3B82F6'
});

await generator.createIntro('intro.mp4', {
  title: 'MyApp',
  tagline: 'Work smarter',
  duration: 3
});

await generator.createOutro('outro.mp4', {
  title: 'Get Started',
  cta: 'Try Free',
  duration: 4
});

See Intelligent Pipeline Guide and Overlays & Effects Guide for complete documentation.