Skip to content

OGMatrix/klartext

Repository files navigation

klartext

Decode the hidden telemetry your dashcam was silently recording.

v1.0.0   Python 3.8+   MIT

offline   open-source   multi-format decoder   HUD compositor


klartext (German: plain text; speaking the unvarnished truth) is a command-line tool that decodes the telemetry stream embedded in dashcam footage and renders a clean HUD overlay onto a copy of the video.

The goal is universal: any dashcam that hides or embeds telemetry — protobuf cues, NMEA sentences, GoPro GPMF, manufacturer-proprietary binary, plain-text subtitle GPS — should be readable through klartext.

The reality today is one format: the Audi A5 (2026, E3 1.2 / MIB4) protobuf-in-tx3g payload that the project was originally built around. The architecture treats this as one decoder among many; new formats live behind the same pipeline. See 04 / Supported Cameras for the current matrix, and 09 / Roadmap for what's next.

Everything happens on your machine. No cloud, no accounts, no telemetry of its own.


Audi A5 (2026) — HUD rendered by klartext from the embedded telemetry track


Contents


01 / Overview

klartext is two pieces glued together:

  1. A decoder that reads telemetry from whatever the camera embedded — and normalises it into a universal frame format with timestamp, GPS, speed, heading, odometer, optional altitude, plus a typed bag of vendor-specific extras.
  2. A renderer that turns those frames into standard outputs (CSV, JSON, GPX) and a clean HUD overlay on a re-encoded copy of the video — Audi-MMI-style by default, configurable.

The decoder is the part that varies between camera vendors. The renderer is the part that doesn't. Everything between the two — the universal KSFFrame / KSFDocument, the writers, the encoder picker, the HUD layout, the watermark, the minimap — is shared across formats.

Today klartext ships with one decoder: the Audi A5 (E3 1.2 / MIB4) protobuf-in-tx3g format. New decoders are added by opening an issue with a sample clip from a format klartext can't read yet — the maintainers handle the decoder work. You don't have to write code; you just have to bring the data. (Writing the decoder yourself is welcome too, but optional.) The workflow is in CONTRIBUTING.md.


02 / Quick Start

Requirements

Component Version Required? Notes
Python ≥ 3.8 yes type-hinted dataclasses
ffmpeg / ffprobe ≥ 5.0 yes must be on $PATH
rich latest yes terminal UI
Pillow ≥ 10.0 optional enables the graphical HUD with minimap. Without it, klartext falls back to ASS subtitle overlay.

Hardware-accelerated encoding is auto-detected in this order: NVIDIA NVENC → Intel QSV → AMD/Mesa VAAPI → libx265 software. Override with --encoder if needed.

Installation

# recommended (includes Pillow for the graphical HUD):
pip install "klartext[hud]"

# minimal (no graphical HUD, ASS subtitle overlay only):
pip install klartext
# or install from source (latest unreleased commit):
git clone https://github.com/OGMatrix/klartext
cd klartext
pip install -e ".[hud]"

Pillow is optional but strongly recommended — it enables the full graphical HUD with satellite minimap and brand mark. Without it, klartext falls back to an ASS subtitle overlay only.

Run

klartext drive.mp4
# or equivalently:
python -m klartext drive.mp4

That is the entire common case. By default klartext writes its outputs next to the input file.

klartext --version

Reports the current version.


03 / Output

For an input drive.mp4, klartext produces:

File Format Purpose
drive.telemetry.csv wide CSV one row per cue, every decoded field
drive.telemetry.json structured JSON scripting / pipeline use, includes raw fields
drive.track.gpx GPX 1.1 drop into any mapping tool
drive.hud.ass Advanced SubStation Alpha the overlay subtitle, re-usable on its own
drive.hud.mp4 HEVC video re-encoded with the HUD burned in
drive.map.html HTML self-contained Leaflet.js interactive route viewer (opt-in: --html-map)
drive.chapters.ffmeta FFMETADATA chapter markers injected during re-encode (opt-in: --chapters)
drive.thumb.jpg JPEG HUD-composited still thumbnail at a chosen timestamp (opt-in: --thumbnail)

The CSV columns map directly to the fields in 06 / Telemetry Field Reference.

The GPX file includes klartext-specific extensions for the fields GPX 1.1 doesn't natively carry (cumulative odometer, GPS C/N₀) — readable by any GPX-aware tool, with the extras ignored cleanly.

If Pillow is installed, the burned-in HUD includes a satellite minimap with a heading-aware GPS marker, the date/time + location panel, a centred speed readout, and a small klartext mark in the lower-right corner. Without Pillow, the same telemetry is shown via the ASS subtitle overlay, minus the minimap.


04 / Supported Cameras

Two axes: the telemetry format (what protocol klartext reads), and the specific hardware known to use that format. Adding a new vehicle to an already-supported format is usually a one-line change; adding a new format is a new decoder module.

Telemetry formats

Status legend: Working = first-class support; Planned = committed roadmap item with a defined approach; In investigation = format identified, feasibility being assessed.

Format Vendors / cameras it covers Status Difficulty
Audi protobuf-in-tx3g Audi A5 (2026), likely Q6 e-tron, A6 e-tron, Porsche Macan EV — all E3 1.2 / MIB4 Working reverse-engineered
GoPro GPMF (gpmd metadata track) GoPro Hero 5+, some Insta360, Sony Action Cam Planned well-documented public spec
DJI SRT subtitle GPS DJI Mavic / Air / Mini, Osmo Action Planned plain text, regex-extractable
NMEA 0183 sidecar Garmin, Viofo, Thinkware, Nextbase, some BlackVue Planned standard GPS protocol
Novatek embedded Viofo A119, generic Novatek-chipset cams In investigation community-RE'd binary atom
BMW integrated dashcam recent BMW models with built-in cam In investigation format undocumented
Mercedes integrated dashcam recent MBUX-based models with built-in cam In investigation format undocumented
Tesla TeslaCam Tesla Model S/3/X/Y In investigation GPS is in vehicle logs, not the clip — feasibility uncertain

Verified hardware

Specific cameras / vehicles confirmed working through actual sample testing.

Manufacturer Model Year Format Status Verified by
Audi A5 2026 Audi protobuf-in-tx3g Working project author

"Working" means: the telemetry stream is detected, every sample parses cleanly, GPS + speed + odometer round-trip correctly, and the rendered HUD matches the in-car (or expected) playback.

Likely compatible — testing welcome

Other vehicles built on the Volkswagen Group E3 1.2 / MIB4 platform with an integrated dashcam are expected to use the same protobuf schema. Candidates, in rough order of confidence:

  • Audi Q6 e-tron (2025+)
  • Audi A6 e-tron (2025+)
  • Audi A6 (current generation)
  • Audi Q5 (next generation)
  • Porsche Macan EV (2024+)

If you own one of these and have a dashcam export to share, please open an issue — your sample is what moves the row from this list to the verified table.

Adding to either table

Both paths are issue-driven and primarily about you bringing the data. You don't need to write code. Open an issue with a sample clip, the ffprobe output, and whatever else you can find (camera model, firmware, sidecar files, manufacturer docs), and the maintainers will handle the decoder work. Writing the decoder yourself is welcome but optional.

  • New hardware on an existing format (e.g., another E3 1.2 Audi): see CONTRIBUTING.md.
  • New format entirely (e.g., a NMEA-sidecar dashcam, a GoPro export): see CONTRIBUTING.md.

05 / How It Works

The pipeline

input.mp4
  → ffprobe                          (identify streams)
  → auto_detect / --decoder          (choose decoder, report confidence %)
  → decoder.decode(...)              (per-format)
  → KSFDocument                      (universal in-memory model)
  → writers (CSV, JSON, GPX, ASS)    (format-agnostic)
  → renderer (Pillow HUD, optional)  (format-agnostic)
  → ffmpeg burn + re-encode          (format-agnostic)
  → input.hud.mp4

Every decoder produces the same KSFDocument (a list of KSFFrame objects plus metadata). Every output writer consumes that shape. New formats only touch the decoder.

The Audi A5 decoder (worked example)

ffprobe on a stock Audi A5 dashcam export reveals an extra track alongside the video and audio:

Stream #0:0  Video    : hevc (Main 10), 3840×2160, 30 fps
Stream #0:1  Audio    : aac, 48000 Hz, stereo
Stream #0:2  Subtitle : mov_text  (tx3g)         ← telemetry channel

The subtitle stream is the entire telemetry channel. The in-car player reads it; every external player ignores it.

Each cue is a 3GPP timed-text payload of the form:

{\an7}<font size="0">PD94bWwgdmVyc2lvbj0iMS4wIj8+CjwhRG9j…</font>

The <font size="0"> makes the cue invisible if a player ever did try to render it. The base64 blob inside decodes to a binary Protocol Buffers message at roughly 5 Hz.

There is no .proto file. There does not need to be: the firmware writes field names as plaintext strings directly into the wire format alongside their values. A single frame looks roughly like:

id200_01  "2026-05-04T07:14:24+00:00"
id200_02  "52.606677242"
id200_03  "11.849491519"
id200_05  9.138                          (speed, m/s)
id200_06  774116.0                       (odometer, m)
idOC_02   "Scharnhorststrasse"
idOC_04   "Stendal"
idOC_06   "DE"
idOC_40   "t11_DEU_1p0_2p50_3p0_1s0"

klartext walks the wire bytes, reads each (tag, name, value) triple, and binds the result into a strongly-typed KSFFrame. No protobuf library is used — the decoder is ~80 lines.

The HUD renderer

When Pillow is installed, klartext renders a graphical HUD that mimics the Audi MMI playback overlay:

  • top-left — semi-transparent panel with date/time + (<country>) <city> – <street>
  • bottom-left — satellite minimap with a heading-aware GPS marker
  • bottom-centre‹‹ NN km/h ›› speed readout
  • bottom-right — small klartext brand watermark

The renderer writes each composite as a frame in a transparent overlay video, which is then composited and re-encoded onto the source by ffmpeg.

When Pillow is not installed, klartext falls back to an ASS subtitle overlay covering the same text content (no minimap, no graphical icons).

The minimap

The minimap composites raster tiles behind a GPS marker:

  • ESRI World Imagery — satellite imagery (the default, no token required).
  • Mapbox satellite-streets — optional, higher detail at low zooms, requires a free token. klartext tracks your monthly tile usage against Mapbox's 50,000-tile free tier and prints what's left at the end of each run.

When the GPS heading is established (after enough samples to derive a stable direction), the marker rotates to point along the track. Before that, it shows a static disc.

Tiles are cached to ~/.cache/klartext/tiles/ so repeated processing of nearby clips reuses what's already on disk.


06 / Telemetry Field Reference

This section documents the Audi A5 schema specifically. Other formats will get their own reference sections as their decoders land.

The Audi A5 dashcam writes two related blocks per cue. Field names appear stable across the firmware versions we've seen; semantics are not always known.

Primary frame — id200_*

Per-cue dynamic measurements. Confirmed through round-trip verification (e.g., the integral of id200_05 matches the delta of id200_06 to within float-rounding).

Field Type Meaning Status
id200_01 string UTC timestamp, ISO 8601 Confirmed
id200_02 string Latitude, decimal degrees, WGS-84 Confirmed
id200_03 string Longitude, decimal degrees, WGS-84 Confirmed
id200_04 float GPS carrier-to-noise ratio (C/N₀), dB-Hz Confirmed
id200_05 float Ground speed, m/s — multiply by 3.6 for km/h Confirmed
id200_06 float Cumulative odometer, metres Confirmed

Context frame — idOC_*

Static and state fields. Some have plaintext semantic content; many are integer flags whose meaning is not yet known.

Status legend: Confirmed = decoded and verified; Hypothesis = best guess from observed values, needs confirmation; Unknown = field name only, no behaviour observed yet.

Field Type Meaning / hypothesis Status
idOC_02 string Street name (--- when off-road / no match) Confirmed
idOC_04 string City Confirmed
idOC_06 string ISO 3166-1 alpha-2 country code Confirmed
idOC_08 string region / sub-city district Hypothesis
idOC_09 int (1) recording active flag Hypothesis
idOC_10 int (0) always 0 in observed data Unknown
idOC_11 int (0) always 0 in observed data Unknown
idOC_12 int (0/1) right turn indicator — 1 while the right stalk is active Confirmed
idOC_13 int (0/1) left turn indicator — 1 while the left stalk is active Confirmed
idOC_14 int (0) always 0 in observed data Unknown
idOC_15 int (0/1) high-beam headlights active Confirmed
idOC_16 int (0) always 0 in observed data Unknown
idOC_19 int (0) always 0 in observed data Unknown
idOC_21 enum always NONE so far — likely a warning category Hypothesis
idOC_24 enum WarningZero / WarningSeven observed — likely a warning level Hypothesis
idOC_25 enum always TextZero so far — likely a text-overlay slot Hypothesis
idOC_26 enum always RequestZero so far — likely a request-type slot Hypothesis
idOC_27 enum always RequestZero so far — likely a second request slot Hypothesis
idOC_28 int (0) always 0 in observed data Unknown
idOC_29 int (0) always 0 in observed data Unknown
idOC_30 int (0) always 0 in observed data Unknown
idOC_31 int (0) always 0 in observed data Unknown
idOC_32 int (0) always 0 in observed data Unknown
idOC_40 string head-unit firmware string Confirmed
idOC_41 string mostly empty; occasionally a second firmware-shaped string — possibly companion-component firmware Hypothesis
idOC_42 string vehicle model identifier Hypothesis
idOC_46 int (0/1) warning triangle / hazard indicator — 1 when active Confirmed

Derived fields

Computed by klartext, not present in the raw stream:

Field Type Meaning
heading float bearing in degrees from north, clockwise, derived from consecutive GPS positions with EMA smoothing
speed_kmh float convenience conversion of speed_ms × 3.6

Help wanted

The fastest way to upgrade an Unknown row to a Hypothesis, or a Hypothesis to Confirmed, is to capture footage of a known event and look at which fields move:

  • a sharp brake → which counter increments?
  • a g-sensor event (speed bump, pothole) → which integer becomes non-zero?
  • crossing a country border → when does idOC_06 flip?
  • a dashcam firmware update → does idOC_41 change? does idOC_42 appear?
  • a lane-assist warning → which enum field changes?

If you find a match, please open a PR against this table. The workflow is in CONTRIBUTING.md.


07 / CLI Reference

klartext INPUT.MP4 [options]

Core

Flag Default Description
INPUT.MP4 the dashcam export to process
-o, --output-dir DIR input dir destination directory
--decoder ID auto force a specific decoder by ID; use list to show all (--decoder list)
--external-telemetry FILE external .gpx sidecar to fill GPS gaps in the decoded data
--version print version and exit
-v, --verbose off print every detected raw decoder field with its type and first observed value
--stats-only off decode telemetry, print trip statistics (speed, distance, GPS, countries …), and exit without writing any output files

Clip controls

Flag Default Description
--preview SECS off process only the first SECS seconds of the clip — useful for fast iteration
--trim START END off process only the [START, END) window; times as [[HH:]MM:]SS[.ff] or bare seconds (e.g. 30 90 or 0:30 1:30)
--speed-unit {kmh,mph} kmh speed display unit used in the HUD, ASS subtitle, the HTML map, and --stats-only output

Exports

Flag Default Description
--no-csv off skip writing the CSV telemetry table
--no-json off skip writing the JSON telemetry file
--no-gpx off skip writing the GPX track
--export-ksf off also write <name>.ksf.json — the full KSF normalised document (useful for scripting)
--html-map off write a self-contained Leaflet.js interactive route viewer (<name>.map.html) with speed-coloured segments, hover panel, and sidebar statistics; internet connection required only for map tiles
--chapters off detect chapter events (clip start, stops, country crossings) and write <name>.chapters.ffmeta; automatically injected into the re-encoded video
--thumbnail [TIMESTAMP] off export a HUD-composited JPEG thumbnail (<name>.thumb.jpg) at TIMESTAMP ([[HH:]MM:]SS[.ff] or bare seconds); omit the value to use the video midpoint

Batch processing

Flag Default Description
--batch DIR off process every MP4 in DIR with the same options; the positional input argument is ignored; prints a per-file ✓/✗ summary at the end

Render & encode

Flag Default Description
--no-burn off skip the video re-encode; only export data + .ass
--no-video off skip HUD rendering and video output entirely; only export telemetry, GPX, and ASS
--stream-copy off embed the ASS subtitle as a soft track via stream-copy — no re-encode, very fast, but the subtitle is not burned in (requires player support for soft subs)
--encoder NAME auto force a specific ffmpeg encoder (hevc_nvenc, hevc_qsv, hevc_vaapi, libx265, libx264)
--crf N 22 quality (CRF / CQ / QP depending on encoder)
--font NAME DejaVu Sans HUD font family
--whatsapp off encode for WhatsApp compatibility: forces libx264, yuv420p, H.264 Main profile level 4.0
--strip-telemetry off drop the hidden telemetry track from the output — recommended when sharing

Minimap

Flag Default Description
--no-map off skip the satellite minimap (use ASS-only HUD, or for offline runs)
--mapbox off use Mapbox satellite-streets tiles instead of ESRI
--mapbox-token TOKEN save a Mapbox token to the config file; can be used standalone without a video file
--map-zoom N 16 satellite tile zoom level for the minimap
--map-size PX auto minimap panel size in pixels (default: 25 % of shorter video dimension, min 180)

Configuration paths

Path Purpose
~/.config/klartext/config.json persisted settings (currently: Mapbox token, monthly usage counter)
~/.cache/klartext/tiles/ cached satellite & navigation tiles

Environment variables MAPBOX_TOKEN or KLARTEXT_MAPBOX_TOKEN are honoured as fallbacks if no token is in the config file.

Privacy note on --strip-telemetry

The hidden telemetry track contains your GPS coordinates, timestamps, street names, and odometer. When you share a dashcam clip with anyone — insurance, police, social media — that track travels with the video unless you strip it. --strip-telemetry produces a clean output that retains the rendered HUD but discards the underlying raw stream.


08 / Watermark Policy

klartext renders a small klartext mark in the lower-right corner of the output video. It is intentionally small (≈10 % of frame width), low-contrast, and unobtrusive.

It exists for two reasons:

  1. Attribution. When a clip with a klartext-style HUD shows up online, it should be obvious which tool produced it.
  2. Provenance. If the underlying telemetry is later disputed, the mark indicates which decoder was used.

Contributors are asked not to remove or disable the watermark in pull requests. Refining its size, placement, contrast, opacity, or styling is welcome; deleting it is not. Forks for personal use are free to do as they wish — that is what open-source means. The request applies to contributions back to the canonical repository.


09 / Roadmap

Highlights, in roughly the order they're expected to land:

Landed since v1.0.0: --preview, --trim, --speed-unit, --html-map, --thumbnail, --stream-copy, --batch, --stats-only, --chapters, PyPI publishing (pip install klartext)

Up next:

  • format coverage — decoders for GPMF, DJI SRT, NMEA 0183 sidecars, Novatek embedded
  • additional HUD modules (speed history, altitude, compass, trip distance)
  • a configurable HUD layout with freely movable components
  • a browser-based HUD designer at klartext.dev
  • expanded vehicle coverage within existing formats (E3 1.2 siblings)

The full plan with status, prioritisation, and open questions lives in ROADMAP.md.


10 / Contributing

klartext is open-source and will stay that way. The shape of the project — first-class Audi support today, every dashcam tomorrow — only works through contributions.

Where you can help:

  • bug reports & fixes — open an issue or a PR
  • security findings — see the dedicated section in CONTRIBUTING.md
  • a new decoder format — share a clip from a dashcam klartext can't read yet, plus everything you can find about it; the maintainers handle the decoder code (writing it yourself is welcome too, but optional)
  • a new vehicle inside an existing format — confirm support by sharing a sample clip from your car
  • reverse-engineering — help fill in the Unknown / Hypothesis rows in the Field Reference
  • features — pick a roadmap item or propose your own
  • documentation — typo fixes, translations, clearer phrasing

The full process, code style, decoder interface, and the new-vehicle workflow live in CONTRIBUTING.md.


11 / License

MIT for the source code. Brand assets in assets/ are © the klartext authors — all rights reserved unless otherwise noted. The embedded glyph outlines in the brand SVGs derive from DejaVu Sans Bold (OFL-1.1).


12 / Acknowledgements

  • the FFmpeg project, without which none of this exists
  • the GoPro GPMF authors for publishing the gpmd specification
  • the DejaVu Sans contributors for an OFL grotesque that survived being chopped into a logo
  • ESRI for the open World Imagery tile service, and Mapbox for a usable free tier
  • everyone who has ever filed an issue with a hex dump attached

klartext.dev

About

Decode dashcam telemetry from cars like Audi A5 (E3 1.2 / MIB4) and burn an in-car-style HUD

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages