In short
To check a camera’s timestamps, film this clock and compare the time shown in each recorded frame with the timestamp the camera or logger gave that frame: camera timestamp − screen clock = how late the timestamp is. The clock shows the moment each frame is on screen, exact to one refresh (16.7 ms at 60 Hz, 8.3 ms at 120 Hz), and checks this device’s clock against UTC. A row of black and white cells encodes the same time and the frame number (CTK-TIME v1) so a script can read every frame of a long recording.
How to Check Camera Timestamps
- Sync this computer’s clock, then open the clock and go fullscreen. The panel says how far the clock is from UTC.
- Point the camera under test at the screen so the digits and the time code fill most of the frame width. Use an exposure shorter than one refresh if you can.
- Record the way you normally log: camera software, data logger or the vehicle’s recording system.
- Pick a frame, read the clock in it (or decode the time code) and note the timestamp your system stored for that frame.
- Subtract: camera timestamp − screen clock. The calculator beside the clock does it and wraps across minute boundaries.
Example: the frame shows 14:32:07.483 and the logger stamped it 14:32:07.521, so the timestamp is 38 ms late. That
figure contains the camera’s exposure and readout, transfer and logging delay, and your monitor’s own input lag, plus or minus one refresh. Repeat with
several frames: a constant result is a fixed offset you can correct, a drifting one means the camera’s clock is not synced.
What the Clock Shows, Exactly
A screen can only change once per refresh, so a clock on it moves in steps. CamTestKit draws each frame with the time that frame is expected on screen, not the moment the code ran, and holds it for the whole refresh, so every camera frame catches one complete reading.
| Display | Clock step |
|---|---|
| 60 Hz | 16.7 ms |
| 120 Hz | 8.3 ms |
| 144 Hz | 6.9 ms |
| 240 Hz | 4.2 ms |
Three things sit between the clock and true time. The step above. Your monitor’s input lag, typically 5–30 ms, which a browser cannot measure; it is constant, so compare cameras on the same monitor. And this computer’s clock: the page checks it against Cloudflare’s time and shows the difference with its uncertainty. If you cannot sync the computer, turn on Correct to UTC to shift the clock by the measured offset.
Syncing Several Cameras
Point every camera at the same screen, record together, then compare the clock each camera recorded at the same moment. With a surround-view or stereo rig, the difference between cameras is their sync error; it does not depend on your monitor’s lag, because every camera sees the same screen.
Choose Three clocks to place copies at the top, middle and bottom of the screen. A rolling-shutter camera reads its rows one after another, so the lower clocks can show a later time than the upper ones in the same frame; the difference shows how long the camera takes to read out.
Finding Dropped and Duplicated Frames
Step through a recording frame by frame. At 30 fps on a 60 Hz screen the clock should advance by about 33 ms and the frame number by 2 every frame. A jump of twice that is a dropped frame; the same reading in two frames is a duplicate. The computer can miss a refresh too, which also repeats a reading, so check the panel’s dropped-frame log for that moment before blaming the camera.
The CTK-TIME Time Code
The row of cells under the digits is a fixed format, so a script can read thousands of frames without OCR. It is one row of 68 equal square cells between two white bars that span exactly the row’s width; white is 1, black is 0, read left to right.
| Cells | Content |
|---|---|
| 0–1 | Start guard: 1 0 |
| 2–45 | UTC time in epoch milliseconds, 44 bits, most significant first (enough until the year 2527) |
| 46–57 | Frame number modulo 4096, Gray-coded, so consecutive frames differ in one cell |
| 58–65 | CRC-8 checksum (polynomial 0x07, initial 0) of the 7 bytes holding cells 2–57 |
| 66–67 | End guard: 0 1 |
If the exposure spans two refreshes, the frame shows two codes on top of each other. The checksum then fails and the frame is rejected rather than misread; take the time from the neighbouring frames. This decoder needs only Python and NumPy:
import numpy as np
from datetime import datetime, timezone
def crc8(data: bytes) -> int:
c = 0
for b in data:
c ^= b
for _ in range(8):
c = ((c << 1) ^ 0x07) & 0xFF if c & 0x80 else (c << 1) & 0xFF
return c
def read_cells(gray, x0, x1, y):
"""Sample the 68 cells along row y of a grayscale frame.
x0, x1: left and right ends of the white bars."""
w = (x1 - x0) / 68
v = np.array([gray[int(y), int(x0 + (i + 0.5) * w)] for i in range(68)], float)
return [int(x > (v.min() + v.max()) / 2) for x in v]
def decode(cells):
"""Return (UTC datetime, frame number mod 4096), or None for a bad frame."""
if len(cells) != 68 or cells[:2] != [1, 0] or cells[-2:] != [0, 1]:
return None
payload = int("".join(map(str, cells[2:58])), 2)
if crc8(payload.to_bytes(7, "big")) != int("".join(map(str, cells[58:66])), 2):
return None # two codes blended, or a misread
ms, g = payload >> 12, payload & 0xFFF
frame = g
while g := g >> 1: # Gray code to binary
frame ^= g
return datetime.fromtimestamp(ms / 1000, timezone.utc), frame
The code always carries UTC, even when the digits show local time. With Correct to UTC on, it carries the corrected time.
Timestamp Clock FAQ
How accurate is an on-screen millisecond clock?
Each reading is exact to one screen refresh: 16.7 ms at 60 Hz, 8.3 ms at 120 Hz. On top of that come the monitor’s input lag, usually 5–30 ms and constant for a given monitor, and the computer’s clock error, which this page measures against UTC and shows with its uncertainty. For absolute accuracy below a few milliseconds, use a GPS-disciplined LED clock.
Can I use it to test ADAS camera timestamps?
Yes. Film the clock with the vehicle camera while the logger records, then compare the clock in each frame with the frame’s logged timestamp. The difference is the timestamp delay plus the monitor’s input lag, within one refresh. Comparing several cameras against the same screen gives their sync error without the monitor’s lag.
Why does the last digit skip numbers?
The screen changes only once per refresh, so at 60 Hz the clock advances in steps of about 16.7 ms. Each reading is the exact time of its refresh; the digits in between are never on screen.
Why does my recording show two times on top of each other?
The exposure lasted longer than one refresh, so the camera saw two readings. Shorten the exposure, add light, or read the time code: its checksum rejects blended frames, so a script can skip them and use the neighbouring frames.
Should the clock show UTC or local time?
Use UTC to compare with GPS or PTP time, or with any logger that records UTC. Local time, the default, is easier to read for a quick check. Time shown also lists every time zone, for a logger set to the time of another region; daylight saving time is applied automatically. The time code always carries UTC, whichever the digits show.