Race Engineer (voice callouts)¶
Race Engineer watches your telemetry and speaks the things a real engineer would tell you over the radio: lap times, personal bests, fuel range, pit windows, engine warnings and — once it knows the track — where you are losing time.
"New personal best, one minute thirty-one point eight." "Fuel remaining, five point two laps." "Pit window opens next lap." "Repeated front-left lockups into turn four."
Speech is generated by the browser, not the server. The datalogger never needs an audio device, PulseAudio, Bluetooth, a desktop, a TTS package, or a cloud API — which is what makes this work identically on a Raspberry Pi, in Docker, on a NAS, or on a Windows PC. Nothing is uploaded, and no microphone permission is requested.
Turning it on¶
- Open the driver dashboard (
/dash) or the standalone page (/engineer). - Click Enable Race Engineer.
- You should hear "Race engineer enabled."
The click matters: browsers only allow audio after a user interaction, and a saved preference does not carry that permission across a browser restart. Race Engineer therefore always waits for one click per page load before it speaks.
The panel distinguishes four separate things, which is usually enough to diagnose a silent setup:
| Row | Meaning |
|---|---|
| Voice preference | you have enabled voice on this device |
| Browser audio | speech synthesis exists and the test utterance went through |
| Active speaker | this device is the one allowed to speak |
| Connection | the WebSocket to the datalogger is up |
| Server callouts | the backend is generating callouts |
| Coaching | whether enough laps have been driven for lap-vs-lap coaching (Coach mode only) |
One speaker at a time¶
You may have the dashboard open on a laptop, a phone, an OBS browser source and the admin page at once. Only one browser speaks — the one that claimed voice output (Use this device for voice output). Everything else still receives the callouts and can show them as on-screen captions, but stays silent.
Only /dash and /engineer may claim voice at all. The OBS overlay (/overlay)
never speaks, so adding overlay sources can't turn your stream into a chorus.
If the speaking browser disappears (tab closed, laptop asleep), the claim is released. Reopening the same page takes it back; another device never picks it up on its own.
The /engineer page¶
/engineer is a minimal standalone surface: connection state, the voice controls,
and a running list of recent callouts. It is intended for
- a phone or tablet propped next to the wheel,
- an OBS browser source that provides stream audio,
- troubleshooting voice output without the dashboard in the way.
What it says, and how much¶
Verbosity is a preset over the callout categories:
| Mode | Speaks |
|---|---|
| Minimal | critical engine warnings, fuel shortage, pit window, final lap |
| Race | everything in Minimal, plus lap times, personal bests, positions, fuel range, race progress |
| Coach | everything in Race, plus repeated lockups and wheelspin, tire balance, bottoming, corner time loss |
Pace and corner feedback are always measured against your best lap of the session — the pace you have already proven in this car, on this track.
Default is Race, which averages one to three spoken messages per lap.
Individual categories can be switched off on top of that (system, lap, pace,
race, position, fuel, strategy, engine, tires, chassis, coaching).
Braking points and speeds are spoken in meters and km/h by default; switch to
feet and mph in Admin → Race Engineer (GT7_RACE_ENGINEER_UNITS). This is a
server setting rather than a per-device one, because the callout is worded before it
reaches a browser.
The server has its own verbosity and category settings in Admin → Race Engineer, and they are a ceiling, not a default: a category the server does not produce never reaches any browser, so a device set to Coach hears nothing extra if the server is capped at Race. Out of the box the server is set to Coach — it produces everything and each device decides what it wants — and the panel dims (with the reason) any category the server has been capped below.
What each category says¶
Every callout belongs to one category, and every category can be switched off. The same table is in the Race Engineer panel under What each category says, so you never have to guess what a toggle controls.
| Category | Says | Example |
|---|---|---|
system |
status messages from Race Engineer itself | "Race engineer enabled." |
lap |
your lap time, every completed lap | "Lap time, one minute thirty-two point five. Two tenths slower." |
pace |
personal bests, and pace slipping away from them | "New personal best, one minute thirty-one point eight." / "Your pace is dropping, eight tenths off your best." |
race |
where you are in the race distance | "Final lap." / "Halfway through the race." |
position |
places gained and lost | "Position gained. You are now position four." |
fuel |
how much further the tank will take you | "Fuel remaining, five point two laps." / "Fuel critical, one point two laps remaining." |
strategy |
pit decisions | "Pit window opens next lap." / "Fuel will be short by one point two laps." |
engine |
mechanical warnings — on at every verbosity | "Water temperature critical." / "Oil pressure low." |
tires |
tire temperature and balance | "Rear tires are running eight degrees hotter than the fronts." |
chassis |
setup feedback: what the car is doing, not you | "The car is bottoming out at turn four." |
coaching |
driving feedback against your best lap | "You are braking early into turn four, about fifteen meters." / "Repeated front-left lockups into turn four." / "You lost three tenths in turn six. You braked eighteen meters earlier and carried five kilometers per hour less at the apex." |
Full detail, callout by callout, with when each one fires:
| Callout | Category | When |
|---|---|---|
| Lap time | lap |
every full lap, compared with your session best |
| Personal best | pace |
a full lap beats your session best |
| Pace dropping | pace |
three laps running average well off your best, none of them back on it |
| Final lap / halfway | race |
race distance milestones, once each per race |
| Position gained / lost | position |
a position change that holds for about a second |
| Fuel remaining | fuel |
once a lap, when the tank is close to mattering |
| Fuel low / critical | fuel |
range drops below 3 / 1.5 laps |
| Fuel shortage | strategy |
two laps running project you cannot reach the finish |
| Pit window | strategy |
the lap you must pit by comes into range |
| Water / oil temperature | engine |
above the limit for 5 s, escalating to critical |
| Oil pressure | engine |
below 2 bar for 1.5 s with the engine pulling |
| Tire temperature / balance | tires |
tires running hot, or one axle/side 8 °C hotter |
| Bottoming out | chassis |
the floor grounds in the same place lap after lap |
| Braking early / late | coaching |
recent laps consistently brake off your best lap's marker |
| Repeated lockups / wheelspin | coaching |
the same wheel, the same place, three times in recent laps |
| Corner time loss | coaching |
after a slower lap: where the time went, and how |
Which laps it trusts¶
A lap the logger only saw part of — capture started mid-lap, or you came out of the garage — still gets a lap time from GT7, and that time is short. Left alone it wins the session, becomes the reference every comparison is made against, and turns every coaching callout into fiction.
So laps are checked against how far recent laps ran. A lap covering materially less of the track cannot become the session best, is dropped from the fuel model, and is marked as partial in the Sessions view. The check is retroactive: a lap that looked fine on its own is retracted once later laps show how long a real lap is, and the fastest remaining full lap takes the best.
Coaching waits for this. Braking points, corner losses and repeated-mistake callouts compare laps by position on the track, which is meaningless until several laps agree on the distance — usually by lap three. Until then the coaching category is simply quiet, and the panel says Coaching: needs a few laps.
When it stays quiet¶
Race Engineer deliberately says nothing when the telemetry source is disconnected, the game is loading or paused, the session is not active, the message's category is off, the same thing was just said, or the message has gone stale. A late callout is worse than none: every message carries an expiry, and one that arrives after it is simply dropped.
When you hear nothing¶
Race Engineer reports where it stopped, so silence is diagnosable rather than mysterious. Check in this order:
- The panel's status rows.
Browser audiosaysneeds a click,armed,speaking, orN failed;Active speakersays whether this device is the one allowed to talk. If speech is failing, a red banner names the reason the speech engine gave. - Admin → Race Engineer.
Callouts emittedcounts what the backend produced;Spoken acksandSpeech failurescount what the browser did with them. Emitted but failing means the problem is entirely in the browser; nothing emitted means the detectors have not fired yet. - The server log logs a warning with the same reason on every failed callout.
What the common reasons mean:
| Reason | What to do |
|---|---|
the browser blocked audio |
The click did not count as permission. Press Test voice. |
no response from the speech engine |
The engine accepted the message and did nothing. The reason names how many voices the browser has: 0 voices means the browser has nothing to speak with (Chrome on Linux needs a speech engine such as speech-dispatcher); with voices present, reload the page — the engine can wedge. |
no audio output device / the audio device is busy |
The browser's output device is unavailable — check the system output, and that the page is not muted in the OS mixer. |
no voice installed for this language |
Pick a specific voice in the Voice dropdown. |
this browser has no speech synthesis |
Use Chrome or Edge; captions still work. |
To tell the app apart from the browser, paste this into the browser console:
speechSynthesis.speak(new SpeechSynthesisUtterance("test one two three"))
If that is silent too, the problem is the browser or the machine's audio, not Race Engineer.
After three failures in a row Race Engineer stops trying and shows captions only — each failed attempt otherwise blocks the queue long enough for the messages behind it to expire. Test voice clears that and tries again.
Browsers¶
Chrome and Edge are the best-supported. Safari (macOS and iOS) works, but loads its voices asynchronously and stops speech when the screen locks. On iOS, keep the page in the foreground.
The OBS embedded browser has historically had unreliable speech support; test it before relying on it for a stream, and fall back to a normal browser window on the same machine if it stays silent. Callout captions still render either way.
If speech is unavailable entirely, the dashboard keeps working normally and callouts appear as on-screen captions — nothing else degrades.
Testing without driving¶
Admin → Race Engineer → Send test callout pushes a callout to every connected browser, which is the quickest way to prove the whole path (server → WebSocket → queue → speech) works.
To exercise real detectors without a console, run the simulated source with a scenario:
GT7_SOURCE=sim GT7_SIM_SCENARIO=fuel_shortage ./dev.sh
Scenarios: practice (default), race, fuel_shortage, overheating,
oil_pressure.