Skip to main content

HoraVox - a multi-language speaking clock using local AI voice models

Project description

HoraVox logotype: a simplistic analog clock and text HORAVOX

pip CI horavox GitHub repo Coverage Status LICENSE MIT

A multi-language speaking clock that announces the time using Piper text-to-speech. It runs entirely offline using local AI voice models -- no API key or internet connection required (except for the initial voice download). It speaks the current hour on the hour using natural language idioms (e.g., "quarter past two", "wpół do czwartej") and supports any language through JSON data files.

Features

  • Natural time idioms -- not just "it is 14:30" but "half past two" (English) or "wpół do trzeciej" (Polish)
  • Classic & modern modes -- idiomatic ("quarter past five") or digital ("five fifteen")
  • Multi-language -- add a new language by creating a JSON file in data/lang/
  • Fully offline -- uses local AI voice models, no API key or cloud service needed
  • Voice management -- browse, download, and auto-detect Piper voices from Hugging Face
  • Bluetooth audio fix -- plays a silent MP3 before speech to prevent clipping on Bluetooth speakers
  • Flexible scheduling -- restrict announcements to a time range (e.g., 7:00--22:00)
  • Configurable interval -- announce every N minutes with --freq (e.g., every 30 min)
  • Volume control -- set volume 0--100% with --volume
  • Background mode -- run as a daemon with --background, stop with --stop
  • Hour beeps -- 2 beeps on the full hour, 1 beep on the half hour
  • Simulated time -- debug with --time HH:MM to set a fake starting time
  • Silent by default -- no terminal output unless --verbose is passed

Requirements

  • Python 3.10+ and pip
  • aplay (ALSA utils, for WAV playback) -- sudo apt install alsa-utils
  • mpg123 (for MP3 playback) -- sudo apt install mpg123

Installation

From PyPI

pip install horavox

This installs the vox command.

From source

git clone https://github.com/jcubic/horavox.git
cd horavox
pip install .

This installs the vox command from the local source, including all dependencies.

Usage

HoraVox uses git-style subcommands:

vox <command> [options]
Command Description
vox clock Run the speaking clock
vox now Speak the current time once
vox stop Stop running background instances
vox voice Manage Piper voice models

Run vox <command> --help for command-specific options.

vox clock

Run the speaking clock in foreground or as a background daemon:

vox clock                                          # announce every hour
vox clock --freq 30                                # every 30 minutes
vox clock --start 7 --end 22                       # only between 7:00-22:00
vox clock --mode modern                            # digital style ("siedemnasta piętnaście")
vox clock --background                             # run as a daemon
vox clock --lang pl --voice pl_PL-darkman-medium   # specific language and voice
vox clock --volume 50                              # 50% volume

Time range accepts H, HH, H:MM, or HH:MM. Supports midnight wrap (e.g., --start 22 --end 6).

Valid --freq values must divide 60 evenly: 1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60.

Classic mode (default) uses idiomatic expressions -- "quarter past five", "wpół do szóstej". Modern mode reads the time digitally -- "five fifteen", "siedemnasta piętnaście".

vox now

Speak the current time once and exit:

vox now                        # speak current time
vox now --time 16:00           # speak a specific time
vox now --mode modern          # digital style
vox now --volume 30            # quiet

vox stop

Stop running background instances:

vox stop                       # interactive selection if multiple instances
vox stop --pid 12345           # stop a specific instance
vox stop --list                # print PIDs (for scripting)
vox stop --list --verbose      # include command lines

When multiple instances are running, vox stop shows an interactive menu with arrow-key selection.

vox voice

Interactive voice browser -- navigate with arrow keys, press i to install, u to uninstall, q to quit:

vox voice                      # interactive voice browser
vox voice --lang en            # for a specific language
vox voice --list               # non-interactive list (for scripting)
vox voice --list --lang pl     # non-interactive for a specific language

Installed voices are marked with [*]. Downloads show a progress bar below the list.

Volume and sound

--nosound is equivalent to --volume 0 -- both skip voice loading and audio playback entirely. Available on vox clock and vox now.

Custom commands

Like git, any executable named vox-<name> in your $PATH can be invoked as vox <name>. This lets you extend HoraVox with your own commands or scripts:

# Create a custom command
cat > ~/bin/vox-greet << 'EOF'
#!/bin/bash
vox now --lang en --voice en_US-lessac-medium
EOF
chmod +x ~/bin/vox-greet

# Use it
vox greet

Adding a new language

Create a JSON file in data/lang/<code>.json (e.g., de.json for German). The file contains two mode sections:

{
  "classic": {
    "hours": ["midnight", "one o'clock", "...", "eleven o'clock"],
    "hours_alt": ["midnight", "one", "...", "eleven"],
    "minutes": {
      "1": "one", "2": "two", "...": "...", "29": "twenty nine"
    },
    "patterns": {
      "full_hour": "{hour}",
      "quarter_past": "quarter past {hour_alt}",
      "half_past": "half past {hour_alt}",
      "quarter_to": "quarter to {next_hour_alt}",
      "minutes_past": "{minutes} past {hour_alt}",
      "minutes_to": "{minutes} to {next_hour_alt}"
    }
  },
  "modern": {
    "hours": ["midnight", "one o'clock", "..."],
    "hours_alt": ["twelve", "one", "..."],
    "minutes": {
      "1": "oh one", "...": "...", "59": "fifty nine"
    },
    "patterns": {
      "full_hour": "{hour}",
      "time": "{hour_alt} {minutes}"
    }
  }
}

Fields

Classic mode (idiomatic -- quarters, halves, past/to):

Field Required Description
hours Yes 24 entries (index 0 = midnight, 12 = noon, etc.) used in {hour} and {next_hour}
hours_alt No 24 entries for alternate forms (e.g., genitive case). Defaults to hours if omitted
minutes Yes Keys "1" through "29" -- spoken forms for minute counts
patterns Yes 6 patterns: full_hour, quarter_past, half_past, quarter_to, minutes_past, minutes_to

Modern mode (digital -- hour + minutes):

Field Required Description
hours Yes 24 entries for full-hour announcements (can include "midnight", "noon")
hours_alt No 24 entries for the hour in {hour_alt} {minutes} patterns. Defaults to hours
minutes Yes Keys "1" through "59" -- spoken forms for all minute values
patterns Yes 2 patterns: full_hour and time

Placeholders

Placeholder Meaning
{hour} Current hour from hours
{hour_alt} Current hour from hours_alt
{next_hour} Next hour from hours
{next_hour_alt} Next hour from hours_alt
{minutes} Minute count from minutes map
{remaining} Minutes remaining to next hour (same source as {minutes})

Pattern rules

Pattern When Example (English)
full_hour :00 "three o'clock"
quarter_past :15 "quarter past three"
half_past :30 "half past three"
quarter_to :45 "quarter to four"
minutes_past :01--:29 (not :15) "ten past three"
minutes_to :31--:59 (not :45) "ten to four"

Project structure

src/horavox/
  __init__.py         Package init
  cli.py              Main script (installed as `vox` via pip)
  data/
    lang/
      en.json         English time data
      pl.json         Polish time data
    blank.mp3         Silent MP3 for Bluetooth audio wake-up
    beep.mp3          Beep sound for hour/half-hour signals
pyproject.toml        Package configuration

~/.horavox/           Runtime data (created automatically)
  voices/             Downloaded Piper voice models (.onnx)
  cache/              Voice catalog cache + PID file
  horavox.log         Spoken words + error log

Development

See CONTRIBUTING.md for development setup, testing, and publishing instructions.

Name

The name of the project is takend from two words from Latin: Hora (hour) + Vox (voice) -- the voice of the hour.

Acknowledge

The logo use Clipart from OpenClipart and font Lovelo.

License

Copyright (C) 2026 Jakub T. Jankiewicz

Released under MIT license

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

horavox-0.2.0.tar.gz (40.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

horavox-0.2.0-py3-none-any.whl (27.9 kB view details)

Uploaded Python 3

File details

Details for the file horavox-0.2.0.tar.gz.

File metadata

  • Download URL: horavox-0.2.0.tar.gz
  • Upload date:
  • Size: 40.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for horavox-0.2.0.tar.gz
Algorithm Hash digest
SHA256 116c4cd09bd06d959707a2328ef4fb1e09852a438e77a4bf3e0482cd89671833
MD5 ad83056ab4d57138fc3d0acc6df3b9da
BLAKE2b-256 5e81f802670dc066c55b93366e1caf8ac6aefcb3d0aa8d98c50a24d66be63915

See more details on using hashes here.

File details

Details for the file horavox-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: horavox-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 27.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for horavox-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 01348c0f6593ae821cb0a774c952cdda4f7ecf6428a7ea1fe5943c0ef1344e01
MD5 66b6b7ad8736951b4ab148260e027014
BLAKE2b-256 16a27ae9307fa64628d31a4adf639eafd3402d12c27ba529fae09c33c00c613e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page