utbd answers SIP calls — through any SIP PBX or provider, or directly — and plays a time signal in the audio format of the NIST shortwave time stations WWV and WWVH: second ticks, minute and hour markers, standard tones, the 100 Hz BCD time code and a spoken time announcement.
Service: time.tgabor.eu
Contact: info@tgabor.eu
Version: 2.0.0
This is an independent service and is not operated by or affiliated with NIST. It reproduces the broadcast format only; its station identification is its own.
Telephone ─── PSTN/VoIP ─── SIP PBX / provider ─── SIP + RTP ─── utbd
│
WWV/WWVH signal generator
(synthesised from UTC)
utbd registers with a SIP PBX or provider and answers every call
routed to it, sending G.711 (A-law or µ-law) RTP. The signal is computed sample by sample from the system
clock, so all callers hear the same broadcast; up to max_calls
callers are served at once. The server's clock should be disciplined
by NTP or GPS.
As described in NIST Special Publication 250-67, NIST Time and Frequency Radio Stations: WWV, WWVH, and WWVB.
| Element | WWV | WWVH |
|---|---|---|
| Second ticks | 5 ms of 1000 Hz | 5 ms of 1200 Hz |
| Protected zone | 10 ms silence before, 25 ms after each tick | same |
| Omitted ticks | seconds 29 and 59 | same |
| Minute marker | 800 ms of 1000 Hz | 800 ms of 1200 Hz |
| Hour marker | 800 ms of 1500 Hz | same |
| Tones (seconds 1–45) | 500 Hz even, 600 Hz odd minutes | 600 Hz even, 500 Hz odd |
| 440 Hz | minute 2, except hour 00 | minute 1, except hour 00 |
| Silent minutes | 29, 43–51, 59 | 0, 8–10, 14–19, 30 |
| Station ID | minutes 0 and 30 | minutes 29 and 59 |
| Voice announcement | starts at :52.5 | starts at :45 |
| UT1 correction | doubled ticks 1–8 (+) or 9–16 (−) | same |
The announcement says "At the tone, H hours, M minutes, Coordinated Universal Time." The minute marker that follows is "the tone".
Relative levels follow the station modulation: ticks and markers 100 %, voice 75 %, tones and time code 50 %.
A modified IRIG-H code, one bit per second, least significant bit first. A pulse of increased 100 Hz amplitude (3.3:1) starts 30 ms after the second: 170 ms = 0, 470 ms = 1, 770 ms = position marker. Second 0 carries no pulse; together with P0 at second 59 it marks the start of the frame. The frame refers to UTC at its start.
| Seconds | Content |
|---|---|
| 2 | DST in effect at 00:00 UTC today |
| 3 | Leap second warning (always 0) |
| 4–7 | Year, units |
| 9, 19, 29, 39, 49, 59 | Position markers P1–P5, P0 |
| 10–13, 15–17 | Minutes, units and tens |
| 20–23, 25–26 | Hours, units and tens |
| 30–33, 35–38, 40–41 | Day of year, units, tens and hundreds |
| 50 | UT1 sign (1 = add to UTC) |
| 51–54 | Year, tens |
| 55 | DST in effect at 24:00 UTC today |
| 56–58 | UT1 correction, 0.1 s units |
- DST rules: the DST bits follow European rules by default
(
dst = eu). Setdst = usfor the US rules used by NIST. - Leap second warning: not set. utbd has no leap second source.
- Agency announcements: the minutes NIST uses for agency announcements (storm warnings, GPS status, geophysical alerts) carry the normal tone.
- Doubled ticks: SP 250-67 does not give the spacing of the second pulse. utbd sends it 100 ms after the first.
The 100 Hz time code is below the 300–3400 Hz telephone band. It passes a G.711 VoIP path unchanged, but an analog line or handset filters it out. Ticks, markers, tones and voice are all in band.
Both are standard distribution packages:
| Library | Debian / Ubuntu | Fedora / RHEL |
|---|---|---|
| spandsp | libspandsp-dev |
spandsp-devel |
| Sofia-SIP | libsofia-sip-ua-dev |
sofia-sip-devel |
apt install build-essential pkg-config libspandsp-dev libsofia-sip-ua-devThe Makefile also finds the Sofia-SIP headers without pkg-config.
sip.c / sip.h hold the SIP user agent and RTP code, shared with
actsd and actsc. For the voice files: Piper (pip install piper-tts, recommended) or
espeak-ng, and optionally sox or ffmpeg for resampling.
make # libraries are found with pkg-config
PIPER_MODEL=/path/to/en_US-john-medium.onnx make voice # see "Voice files"
sudo make install-service
sudo nano /etc/utbd/utbd.conf
sudo systemctl enable --now utbd
journalctl -fu utbdThe announcement is assembled from WAV files in voice_dir:
at_the_tone, hour, hours, minute, minutes, utc,
station_id, 0–19, 20, 30, 40, 50 (all .wav, 16-bit PCM,
any sample rate). Without the files, utbd runs without voice
announcements.
gen-voice.sh [DIR] [wwv|wwvh] creates them:
- Piper (neural TTS, natural sounding) when
PIPER_MODELpoints to a voice model. Recommended voices, both trained only on public-domain LibriVox recordings: en_US-john-medium (male) for WWV and en_US-kristin-medium (female) for WWVH. See License about other voices. Download the.onnxand.onnx.jsonfiles of the voice. - espeak-ng otherwise. It is available everywhere but sounds robotic.
pip install piper-tts
PIPER_MODEL=en_US-john-medium.onnx ./gen-voice.sh voice wwvPITCH=-3 makes the voice deeper by that many semitones (sox or
ffmpeg required). Up to about −3 the words stay as clear as the
original.
Recordings of a human voice saved under the same names sound best. Any sample rate works: utbd band-limits and resamples the files to 8 kHz, and trims the silence TTS engines add around each word.
/etc/utbd/utbd.conf (key = value, # comments). Command-line
options override the file.
| Key | Default | Meaning |
|---|---|---|
registrar |
— | SIP PBX or provider to register with, host[:port] |
username, password |
— | SIP account (username required with a registrar) |
allow |
the registrar | Who may call in: any, or IPv4 addresses / CIDRs |
sip_port |
5060 | Local SIP port (UDP) |
rtp_ports |
10200-10399 | RTP port range (UDP), two ports per simultaneous call |
local_ip |
automatic | Local address for SIP and RTP (default: the one that routes to the registrar) |
public_ip |
— | Address advertised in SIP and SDP behind NAT |
station |
wwv |
wwv or wwvh format |
voice_dir |
/usr/local/share/utbd/voice |
Voice WAV files |
dut1 |
0 | UT1 − UTC in 0.1 s (−7..7), from IERS Bulletin A |
dst |
eu |
DST rules for the time code: eu, us, none |
advance_ms |
0 | Send the signal early to offset path delay |
max_calls |
8 | Simultaneous listeners |
max_call_sec |
180 | Call length limit |
Either registrar or allow must be set.
utbd registers like a SIP phone; the PBX routes a number to it. Asterisk (PJSIP):
; pjsip.conf — needs a UDP transport, e.g. [transport-udp]
[utbd]
type=endpoint
context=from-internal
disallow=all
allow=alaw,ulaw
auth=utbd-auth
aors=utbd
[utbd-auth]
type=auth
auth_type=userpass
username=utbd
password=changeme
[utbd]
type=aor
max_contacts=1
qualify_frequency=60
; extensions.conf — route a number to utbd
exten => 1236,1,Dial(PJSIP/utbd)Without a PBX, set allow to the callers' addresses and call
sip:time@<utbd address> directly.
Open sip_port and rtp_ports (UDP) in the firewall for the PBX.
Behind NAT, forward them and set public_ip.
utbd 1.x used IAX2. Replace host/port with
registrar = host[:port], peername with username and secret
with password, and replace the iax.conf peer with a PJSIP
endpoint as above.
--render writes the signal to an 8 kHz WAV file:
# Two minutes from the current minute
utbd --render wwv.wav --duration 120 --voice-dir voice -c /dev/null
# Around the top of an hour, WWVH format
utbd --render top.wav --start "2026-10-24 22:59" --duration 180 --station wwvh -c /dev/nullutbd only reads its own audio files and sends audio. It does not
interpret anything a caller sends: received RTP is discarded. It
accepts calls only from allow (by default, the registrar's
address); others get 403 Forbidden. RTP is sent only to the
address negotiated in SDP. Caller ID is sanitised before logging, and calls are limited
in number and length. The systemd unit runs utbd as an unprivileged
user with a system-call filter and a read-only file system.
Copyright (C) 2026 Gabor Temesi info@tgabor.eu
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
The full license text is in COPYING.
SPDX-License-Identifier: GPL-3.0-or-later
The program is linked with these libraries; no third-party source code is included in this repository.
| Component | License | Project |
|---|---|---|
| spandsp | LGPL-2.1-only (library) | https://github.com/freeswitch/spandsp |
| Sofia-SIP | LGPL-2.1-or-later | https://github.com/freeswitch/sofia-sip |
Both libraries may be used by GPL-3.0 programs. Distribution packages of Sofia-SIP may link OpenSSL 3 (Apache-2.0), which is compatible with GPL-3.0 as well.
Note for binary distributors. Besides its LGPL-2.1 code, the
spandsp library contains a few files licensed GPL-2.0-only
(image_translate.c in 0.0.6; also sprt.c and v150_1*.c in newer
snapshots). GPL-2.0-only and GPL-3.0 code cannot be combined in one
work. This program does not use those parts, and none of this affects
building it from source or running it. If you distribute binaries,
link spandsp statically (the linker then includes only the LGPL-2.1
modem objects that are used, and the LGPL-2.1 relinking terms apply)
or use a spandsp build without the GPL-2.0-only files.
gen-voice.sh runs Piper or espeak-ng as separate programs. Both are
GPL-3.0-or-later; their license does not cover the speech they
produce. The voice models have their own terms:
| Voice | Use | Training data |
|---|---|---|
| en_US-john-medium | WWV (male) | Public-domain LibriVox recordings (fine-tuned from kristin) |
| en_US-kristin-medium | WWVH (female) | Public-domain LibriVox recordings |
Avoid voices fine-tuned from lessac (such as joe, mike and
ryan): the lessac dataset is licensed for research use only. The
public-domain norman voice is not recommended either: it garbles
most isolated words, such as the digits of the announcement.
The broadcast format follows NIST Special Publication 250-67, a work of the U.S. Government.