# What Is the Journey Model in Google Timeline Visualizer? Core Data Structure Explained

> Understand the Journey model in Google Timeline Visualizer. Discover this lightweight data structure for location history rendering, featuring timing, distance, and video settings.

- Repository: [mahlernim/google-timeline-visualizer](https://github.com/mahlernim/google-timeline-visualizer)
- Tags: internals
- Published: 2026-08-23

---

**The Journey model is a lightweight data structure that represents a contiguous segment of location history selected for video rendering, containing timing parameters, distance mapping functions, and video configuration settings.**

In **mahlernim/google-timeline-visualizer**, the *Journey* serves as the central abstraction bridging user selection and video output. This open-source tool converts Google Timeline location data into animated travel videos, and the Journey model encapsulates everything needed to transform raw coordinates into a time-compressed visualization.

## Journey Model Properties and Purpose

A *Journey* is not implemented as a formal Python class. Instead, it functions as a passed-around data structure with six core properties that drive the rendering pipeline:

| Property | Function |
|----------|----------|
| `start_ts` | Epoch-millisecond timestamp of the first location point |
| `end_ts` | Epoch-millisecond timestamp of the last location point |
| `duration` | Target video length in seconds (clamped 10–300s) |
| `fps` | Frames-per-second derived from resolution preset |
| `distance_mapper` | Callable mapping video progress (0–1) → travelled distance |
| `preview_aspect` | Canvas aspect ratio for preview and thumbnail generation |
| `title_template` | Display title supporting `{name}` and `{year}` placeholders |

These properties originate in [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py), where the CLI parses user arguments and constructs the journey before entering the render loop.

## Building the Distance-to-Progress Mapper

The most sophisticated Journey component is the `distance_mapper` created by `build_journey_timing`. This function generates a **monotonic spline** that translates normalized video progress into cumulative real-world distance.

Located at [lines 421–426 of [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py)](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py#L421-L426), this mapper enables three compression modes:

- **off** — Linear mapping preserves original speed variations
- **balanced** — Moderate compression of long stationary periods
- **stronger** — Aggressive compression emphasizing movement

The spline preserves route geometry while allowing temporal manipulation. This means a 10-hour drive followed by a 30-minute walk can compress into a 60-second video that still accurately traces both paths.

```python
from visualizer import build_journey_timing

# Cumulative distances (km) along the route

cum_dist = [0.0, 1.2, 3.5, 7.8, 12.0]

# Create mapper with balanced compression

distance_at = build_journey_timing(cum_dist, compression='balanced')

# Query distance at 45% through video

km_traveled = distance_at(0.45)  # Returns interpolated kilometers

```

## Journey Rendering Loop Implementation

The rendering engine consumes the *Journey* structure in the main visualization loop. Around [lines 1120–1135 in [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py)](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py), the code:

1. Validates elapsed time against `journey.duration`
2. Computes `j_progress` as elapsed/duration ratio
3. Invokes `distance_mapper(j_progress)` to determine current position
4. Renders the corresponding map frame
5. Triggers outro transition upon completion

This loop is frame-rate agnostic — the same Journey renders correctly at 24fps or 60fps because timing derives from wall-clock duration rather than frame count.

## CLI and Web UI Usage

Users create Journeys through either interface. The CLI exposes all parameters directly:

```bash
python -m visualizer \
    --input takeout-sample.json \
    --start "2022-03-01T08:00:00Z" \
    --end "2022-03-01T10:30:00Z" \
    --duration 45 \
    --preset portrait \
    --title "My Spring 2022 Journey"

```

The web UI mirrors this structure in TypeScript. The `Journey` interface in [`src/journey.ts`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/src/journey.ts) maintains equivalent fields for browser-based configuration:

```typescript
export interface Journey {
    startMs: number;
    endMs: number;
    durationSec: number;
    previewAspect: 'square' | 'portrait' | 'landscape';
    title: string;
}

```

## Terminology Distinction

Per [`docs/terminology.md`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/docs/terminology.md), the project explicitly differentiates a *Journey* from a generic date range. While Google Timeline exports contain years of location history, a *Journey* specifically denotes **the selected period designated for video conversion**. This distinction matters for documentation, error messages, and user guidance throughout the codebase.

## Summary

- The **Journey model** in Google Timeline Visualizer is a property bag, not a class, defined by timing parameters and a distance-mapping function
- **`build_journey_timing`** in [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py) creates the progress-to-distance spline with configurable compression
- The **rendering loop** at lines 1120–1135 drives video generation using Journey-derived timing
- Both **CLI and web interfaces** construct equivalent Journey structures for cross-platform consistency
- Project **documentation** in [`docs/terminology.md`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/docs/terminology.md) formalizes Journey as a domain-specific term for video-bound location segments

## Frequently Asked Questions

### Is the Journey model a Python class or a dictionary?

The Journey model is neither a formal class nor a required dictionary schema. It operates as a **loosely-structured data structure** where functions accept and pass around objects with expected properties. The code in [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py) accesses attributes like `journey.start_ts` and `journey.distance_mapper` without enforcing a specific type.

### How does the compression setting affect the final video?

Compression controls the **time-distortion curve** applied to the route. With `compression='off'`, video time correlates linearly with wall-clock time. `balanced` and `stronger` modes increasingly flatten the curve during slow or stationary periods, keeping motion visible while shortening overall duration. The underlying geometry remains unchanged—only the temporal pacing shifts.

### Can I create multiple Journeys from one Timeline export?

Yes. The same Google Timeline JSON export can generate unlimited Journeys by specifying different `--start` and `--end` timestamps. Each invocation of [`visualizer.py`](https://github.com/mahlernim/google-timeline-visualizer/blob/main/visualizer.py) constructs an independent Journey structure with its own timing mapper and rendering parameters.

### What happens if my selected duration exceeds 300 seconds?

The `duration` property is **clamped to the 10–300 second range** during Journey construction. Values below 10 seconds round up; values above 300 seconds truncate to 300. This constraint ensures manageable file sizes and predictable rendering times across the supported resolution presets.