Heatmap Generator

Heatmap Generation Devlog - Building an Animated Heatmap Generator

🎮 Building a Heatmap Generation System

October 2025 - Development Log

What is Heatmap Generation?

This is a TypeScript-based tool that transforms game replay data into beautiful animated heatmap videos. The tool processes replay JSON files and generates multi-angle visualizations showing where the action happens.

Project Stats:

  • Language: TypeScript + Node.js
  • Key Tech: Canvas API, Worker Threads, FFmpeg
  • Features: Multi-threaded rendering, 3-view heatmaps, video composition

The Challenge

  1. Parse complex replay JSON structures with thousands of position snapshots
  2. Generate heatmaps from three different camera angles (top, side, front)
  3. Process this data efficiently without running out of memory
  4. Combine all views into a single synchronized video

Architecture Overview

Data Pipeline

The system follows a sophisticated multi-stage pipeline:

  1. Replay Reader - Parses JSON replay files containing player positions, rotations, health data, and timestamps
  2. Heatmap Generator - Converts 3D position data into 2D heatmap visualizations with Gaussian blur
  3. Multi-threaded Renderer - Distributes frame generation across CPU cores using Worker Threads
  4. Video Compositor - Combines three views into a 4-panel layout and encodes to MP4

Parallel Processing Magic

One of the most interesting aspects of this project is the parallel processing architecture. The system dynamically calculates how many chunks to split the work into based on available CPU cores:

const numCPUs = os.cpus().length;
const chunksPerView = Math.ceil(maxWorkers / totalViews);
// Each view is split into chunks for parallel processing

This means that on an 8-core machine, the system can process 8 different chunks simultaneously, dramatically reducing render times.

Recent Improvements: Pure TypeScript Video Generation

Migrating from Python to TypeScript

Initially, I used Python scripts (create_4panel_video.py) to combine the generated heatmap frames into videos. However, this created a dependency on Python and made the pipeline less elegant. The recent development cycle focused on migrating to a pure TypeScript solution.

Introducing video_creator.ts

The new video_creator.ts module brings several improvements:

  • Worker Thread Pool - Limits concurrent workers to prevent memory exhaustion (max 8 workers)
  • Chunked Processing - Processes 50 frames at a time to keep memory usage low
  • Progress Tracking - Real-time progress bars show frame generation status
  • 4-Panel Layout - Creates beautiful 2×2 grid with labeled views

The video worker generates each frame by:

  1. Loading three PNG images (front, side, top views)
  2. Creating a 2x canvas with double the dimensions
  3. Drawing each view in the correct position
  4. Adding text labels with outlined text for readability
  5. Saving the combined frame

Memory Management

A critical challenge was preventing memory buildup when processing thousands of frames. The solution:

const framesPerChunk = 50; // Process in small batches
const maxConcurrentWorkers = Math.min(8, numCPUs);
// Limit concurrent workers to avoid memory issues

By processing in small batches and limiting concurrent workers, the system can handle hours of replay data without exhausting RAM.

The Beautiful Heatmap Algorithm

The heatmap visualization uses a classic blue → green → yellow → red gradient:

  • Blue: Low activity areas
  • Green: Moderate activity
  • Yellow: High activity
  • Red: Hotspots (intense combat zones)

Each position snapshot is rendered with a Gaussian blur kernel, creating smooth, organic-looking heat patterns rather than pixelated dots. The blur uses an exponential falloff:

const weight = Math.exp(-distance² / (2 × blurRadius²));

This creates realistic "heat" that radiates from combat hotspots.

Multi-View Rendering

The system generates three synchronized views:

  1. Top View - X,Z coordinates (bird's eye view of the battlefield)
  2. Side View - Z,Y coordinates (shows altitude changes and vertical combat)
  3. Front View - X,Y coordinates (horizontal spread and height distribution)

Each view reveals different tactical information about how players use the 3D space during combat.

Performance Optimizations

Chunked Frame Generation

Originally, each view was processed as a single unit. Now, frames are divided into chunks that can be processed independently. This provides several benefits:

  • Better CPU utilization (more tasks than cores)
  • Finer-grained progress tracking
  • More resilient to individual task failures

Timelapses

The system supports configurable timelapse speeds:

const targetFPS = 30;
const timelapseSpeed = 10;  // 10x faster than real-time
const framesPerSecond = targetFPS / timelapseSpeed;

A 5-minute game can be compressed into a 30-second video showing the entire flow of combat.

Technical Deep Dive: Worker Threads

Node.js Worker Threads enable true parallel processing. Each worker:

  1. Receives a chunk of frames to process via workerData
  2. Loads and parses the replay data independently
  3. Generates heatmap frames for its assigned range
  4. Reports progress back to the main thread via message passing
  5. Signals completion when done

The main thread maintains a worker pool, ensuring that as soon as one worker finishes, a new task is assigned:

while (taskIndex < tasks.length || activeWorkers.size > 0) {
    // Fill worker pool to capacity
    while (activeWorkers.size < maxWorkers && taskIndex < tasks.length) {
        const task = tasks[taskIndex++];
        startWorker(task);
    }
    // Wait for at least one worker to complete
    await Promise.race(workerPromises);
}

CLI Progress Visualization

The system provides rich terminal feedback using cli-progress:

  • One progress bar per view (showing consolidated progress across all chunks)
  • Active worker status bar showing which chunks are being processed
  • Video frame generation progress
  • Percentage completion and frame counts

This makes it easy to monitor long-running renders and identify bottlenecks.

Results: The 4-Panel Video

The final output is a high-quality MP4 video showing:

  • Top-left: Front view
  • Top-right: Side view
  • Bottom-left: Top view
  • Bottom-right: Reserved for future features

Each frame is clearly labeled, and the heatmap builds up over time, revealing the tactical flow of the match.

Lessons Learned

1. Memory is the Real Enemy

When processing thousands of high-resolution images, memory management becomes critical. Chunked processing and limited concurrency prevent out-of-memory crashes.

2. Worker Threads are Powerful

Node.js Worker Threads provide true parallelism for CPU-intensive tasks. The speedup is nearly linear with core count.

3. Progress Bars Matter

For long-running processes, good user feedback is essential. Users need to know the system is working and how long to wait.

4. Avoid Language Mixing

Migrating from Python to TypeScript for video generation simplified dependencies and made the entire pipeline more maintainable.

Future Plans

The project has several exciting potential additions:

  • Kill/Death Markers - Highlight significant events
  • Team Heatmaps - Show separate heatmaps for each team
  • Time Counter - Display elapsed time on the video
  • Map Overlay - Show terrain features underneath the heatmap
  • Stats Panel - Use the 4th panel for real-time statistics
  • Web Interface - Upload replays and generate videos online

Conclusion

This heatmap generation system demonstrates how game replay data can be transformed into compelling visualizations. By leveraging modern JavaScript features like Worker Threads, Canvas API, and powerful libraries like FFmpeg, we can build sophisticated video generation tools entirely in TypeScript.

The journey from simple single-threaded rendering to a fully parallelized, memory-efficient pipeline has been incredibly educational. Seeing the heatmaps reveal player behavior patterns and tactical hotspots makes all the optimization work worthwhile.

Thanks for reading! Feel free to leave comments or questions below. 🚀


Tags: gamedev, typescript, nodejs, visualization, heatmaps, video-generation, canvas-api, worker-threads, performance-optimization

Comments

Popular Posts