DEV Community

Cover image for Technical Deep-Dive: Building an AI-Powered Hand-Drawn Whiteboard Video Generator with Revideo & Rough.js
Harish Kotra (he/him)
Harish Kotra (he/him)

Posted on

Technical Deep-Dive: Building an AI-Powered Hand-Drawn Whiteboard Video Generator with Revideo & Rough.js

Visual storytelling is one of the most effective ways to communicate complex technical subjects—whether explaining how a Kubernetes Control Plane coordinates worker nodes, how Retrieval-Augmented Generation (RAG) indexes document embeddings into a vector database, or how Kafka Consumer Groups process partition offsets.

However, creating high-quality whiteboard animation videos traditionally requires hours of manual keyframing in video editors or software like VideoScribe.

In this deep-dive, we will explore the architecture and implementation of AI Whiteboard Video Generator—a full-stack web application that takes natural language prompts and automatically synthesizes hand-drawn Excalidraw-style whiteboard videos alongside executable Revideo motion graphics code.


System Architecture & Data Flow

The application is built around a multi-stage pipeline:

┌─────────────────────────────────────────────────────────────────────────┐
│                              1. USER INPUT                              │
│         Prompt: "Explain how RAG (Retrieval Augmented Generation) works" │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                          2. STRUCTURED LLM AGENT                        │
│   Gemini 2.5 Flash / OpenAI JSON Mode -> Parses concept into scenes     │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │
                                     ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                       3. WHITEBOARD PLAN SCHEMA                         │
│   • Scene 1: Document Chunking & Embedding into Vector DB               │
│   • Scene 2: Similarity Search & LLM Prompt Context Augmentation        │
│   • Scene 3: Response Synthesis & Highlight Swipe                      │
└────────────────────────────────────┬────────────────────────────────────┘
                                     │
                 ┌───────────────────┴───────────────────┐
                 │                                       │
                 ▼                                       ▼
┌───────────────────────────────────┐   ┌───────────────────────────────────┐
│     4A. ROUGH CANVAS PLAYER       │   │    4B. REVIDEO MOTION CODE GEN    │
│  • Rough.js Canvas API            │   │  • Programmatic @revideo/2d code  │
│  • Real-time interpolation        │   │  • Organic Jitter & Spring Ease   │
│  • Multiline text auto-scaling    │   │  • Timeline Voiceover Audio Sync  │
└───────────────────────────────────┘   └───────────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

1. Structuring the AI Prompt for Visual Precision

One of the biggest challenges in AI-generated visual diagrams is preventing overlapping text, clipped container boxes, and unreadable arrow connectors.

To solve this, the LLM is guided by a strict layout & design system prompt:

export const WHITEBOARD_SYSTEM_PROMPT = `You are an expert instructional illustrator and whiteboard animator.
Your task is to take an explanation request and generate a structured JSON Whiteboard Plan.

STRICT LAYOUT & DESIGN RULES:
1. Break down the concept into 2 to 4 clear sequential scenes.
2. Canvas coordinate space: (0,0) is screen center. x spans -300 to +300, y spans -150 to +150.
3. Box & Container Sizing: Make rectangles, rounded_rectangles, databases, and clouds at least 150-180px wide and 100-130px tall so labels fit without clipping.
4. Multiline Labels: Always break long text or titles into 2-3 short lines using '\\n' (e.g. "Control Plane\\n(API Server)" or "Vector DB\\n[Embeddings]").
5. Non-overlapping Spacing: Keep at least 90-120px distance between centers of adjacent shapes.
6. Arrows & Connectors: Connect from outer edge of source element to outer edge of target element. Do NOT overlap shapes or text labels.
7. Maximum 5-7 objects per scene. Do NOT overcrowd.
`;
Enter fullscreen mode Exit fullscreen mode

2. Real-Time HTML5 Rough.js Canvas Rendering

For immediate in-browser playback, the application utilizes roughjs to render sketch-style vector primitives on an HTML5 <canvas>.

Solving Text Overflow with Auto-Scaling Multiline Typography

In hand-drawn diagrams, box dimensions vary. To ensure text labels never overflow containers or clip arrow bounds, a custom multiline text scaler dynamically calculates the bounding box width and scales down the font size proportionally:

function drawMultilineText(
  ctx: CanvasRenderingContext2D,
  text: string,
  x: number,
  y: number,
  fontSize: number = 16,
  fontFamily: string = 'Poppins, Arial, sans-serif',
  fontWeight: string = '500',
  color: string = '#141413',
  align: CanvasTextAlign = 'center',
  maxWidth?: number
) {
  if (!text) return;
  const lines = text.split('\n');

  let effectiveFontSize = fontSize;
  ctx.font = `${fontWeight} ${effectiveFontSize}px ${fontFamily}`;

  if (maxWidth && maxWidth > 20) {
    let maxLineLen = 0;
    lines.forEach((l) => {
      const w = ctx.measureText(l).width;
      if (w > maxLineLen) maxLineLen = w;
    });
    // Dynamically scale down font if text line exceeds container padding
    if (maxLineLen > maxWidth) {
      effectiveFontSize = Math.max(11, Math.floor(fontSize * (maxWidth / maxLineLen)));
      ctx.font = `${fontWeight} ${effectiveFontSize}px ${fontFamily}`;
    }
  }

  const lineHeight = effectiveFontSize * 1.25;
  const totalHeight = lines.length * lineHeight;

  ctx.fillStyle = color;
  ctx.textAlign = align;
  ctx.textBaseline = 'middle';

  const startY = y - totalHeight / 2 + lineHeight / 2;
  lines.forEach((line, index) => {
    ctx.fillText(line, x, startY + index * lineHeight);
  });
}
Enter fullscreen mode Exit fullscreen mode

3. Revideo Code Generation (@revideo/2d)

Beyond browser previewing, developers often want to programmatically render video files for YouTube Shorts, TikTok, or documentation sites.

The revideoGenerator.ts module translates the JSON scene graph into executable @revideo/2d code.

Organic Hand-Drawn Jitter & Spring Overshoot Easing

To ensure Revideo animations don't feel artificially stiff or robotic, we introduced two mathematical physics helpers:

  1. Jitter Variance (jitter): Adds subtle random offsets to shape coordinates, mimicking hand-drawn human inaccuracy.
  2. Spring Overshoot Easing (springEase): Dampened sine-wave spring dynamics that cause elements to slightly overshoot their target size before settling naturally.
/** Adds subtle positional variance to shapes, mimicking hand-drawn Excalidraw primitives */
function jitter(val: number, amount = 2.5): number {
  return val + (Math.random() - 0.5) * amount * 2;
}

/** Spring-based overshoot easing for smooth organic hand-drawn movement */
function springEase(t: number): number {
  if (t <= 0) return 0;
  if (t >= 1) return 1;
  const c4 = (2 * Math.PI) / 3;
  return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
}
Enter fullscreen mode Exit fullscreen mode

Generated Revideo Scene Code Example

Here is an snippet of the generated Revideo TypeScript code:

import { makeScene2D, Rect, Line, Txt, Node, createRef, all, easeOutBack } from '@revideo/2d';

export default makeScene2D(function* (view) {
  const mainContainer = createRef<Node>();
  view.add(<Node ref={mainContainer} />);

  // --- Revideo Audio Track Synchronization Pipeline ---
  // Track 1 [VOICEOVER]: "rag_narration.mp3" (18.0s, Vol: 80%)
  //   • Sync Marker [Indexing Documents into Vector DB]: startAt = 0.0s -> Narration: "First, documents are chunked into embeddings..."

  // --- Scene 1: Indexing Documents into Vector DB ---
  const scene0_Container = createRef<Node>();
  mainContainer().add(<Node ref={scene0_Container} />);

  const ref_doc_box = createRef<Rect>();
  yield* drawBox(
    scene0_Container(),
    ref_doc_box,
    { x: -220, y: 0, width: 150, height: 130, color: '#0284c7', fill: '#e0f2fe', label: 'Docs & PDFs\n(Raw Data)' },
    0.8
  );
});
Enter fullscreen mode Exit fullscreen mode

4. Audio Track Management & Timeline Synchronization

Audio is crucial for instructional videos. The application features an Audio Panel where users can:

  • Drag and drop local MP3/WAV/M4A voiceover recordings or ambient audio.
  • Fine-tune volume levels per track.
  • Automatically bind audio sync markers to scene timeline timestamps (t = 0.0s, t = 6.0s, etc.).

By combining structured Gemini 2.5 Flash prompts, Rough.js vector canvas drawing, and Revideo motion code generation, AI Whiteboard Video Generator bridges the gap between static diagrams and animated instructional media.

Code & more: https://www.dailybuild.xyz/project/207-ai-whiteboard

Top comments (0)