What Is the Journey Model in Google Timeline Visualizer? Core Data Structure Explained
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, 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#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.
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), the code:
- Validates elapsed time against
journey.duration - Computes
j_progressas elapsed/duration ratio - Invokes
distance_mapper(j_progress)to determine current position - Renders the corresponding map frame
- 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:
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 maintains equivalent fields for browser-based configuration:
export interface Journey {
startMs: number;
endMs: number;
durationSec: number;
previewAspect: 'square' | 'portrait' | 'landscape';
title: string;
}
Terminology Distinction
Per 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_timinginvisualizer.pycreates 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.mdformalizes 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 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →