Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

klipper-voice-cues

Spoken status announcements for Klipper — without stalling the printer.

Your printer tells you what it is doing out loud: "Starting bed mesh calibration", "Filament runout", "Print completed". 33 clips included, a four-level verbosity setting so it is not constantly talking at you, an optional volume slider in KlipperScreen and Mainsail, and tooling to generate your own clips in a matching voice.

MIT licensed. Python 3 standard library only, no pip installs on the printer.


Why this is not just "call aplay from a macro"

That is where everyone starts, and it has three problems that are not obvious until you hit them. All three are solved here, and all three are worth knowing about even if you write your own.

1. RUN_SHELL_COMMAND blocks Klipper's gcode queue

This is the big one. RUN_SHELL_COMMAND does not return until the command finishes, and the gcode queue waits. Call aplay directly and the printer stops for the entire length of the clip.

With four-second announcements and three of them in PRINT_START, that is twelve seconds of a machine standing still. Mid-print it is worse: a stall with a hot nozzle sitting on the part leaves a blob in the wall. That is not hypothetical — it is what prompted this package.

Everything here goes through scripts/play_sound.sh, which nohups the player and exits. Measured on a Raspberry Pi 4: 0.060 s against a 0.011 s bare-gcode baseline, versus the multi-second block it replaces.

If you take one thing from this repo, take this one. It applies to any shell command you might fire mid-print.

2. Your sound device is asleep, and eats the first second

Cheap HDMI and USB audio devices power down between clips. The next stream starts playing into a sink that has not finished waking, and the beginning is simply gone. You get "…leted" instead of "Print completed".

The fix is a lead-in buffer: about a second of digital silence at the head of every file, which the device consumes while it wakes.

This is the caveat that costs people the most time, because the symptom looks like a bad recording rather than a hardware behaviour. All clips here carry 1.2 s of leading silence, and tools/process_sounds.py adds it to anything you generate.

It also means your clips will be longer than the words in them, and that is correct. Do not trim it out to "tidy them up".

Since playback is detached, that second costs the printer nothing — it delays the sound, not the machine.

3. The mixer maxes out at unity gain

100% on the ALSA mixer is 0.00 dB — no attenuation, not a boost. If the clips are quiet, the volume control cannot fix it; loudness has to come out of the files.

tools/process_sounds.py handles that: high-pass, RMS targeting, and a look-ahead limiter. See docs/GENERATING.md.

And the volume scale is dB, not loudness — amixer's "50%" is about −25 dB, so a raw slider has two-thirds dead travel. The macro applies a square-root curve to fix it.


Install

cd ~/printer_data/config
git clone https://github.com/Simon-CR/klipper-voice-cues.git voice_cues
sudo apt install -y alsa-utils

You also need gcode_shell_command — from kiauh (Advanced → G-Code Shell Command) or klippain-shelltools.

Then:

  1. Find your audio device

    aplay -L | grep -i -A1 'hdmi\|usb\|headphone'
    aplay -D sysdefault:CARD=vc4hdmi0 voice_cues/sounds/print_started.wav

    Iterate until you hear it. If nothing works at all, see docs/HARDWARE.md.

  2. Edit voice_cues/config.sh — set SOUND_DIR and ALSA_DEVICE.

  3. Edit the two paths at the top of voice_cues/voice_cues.cfg, plus the two [gcode_shell_command] paths just below them. They ship pointing at /home/pi/printer_data/config/voice_cues/.

  4. Add to printer.cfg:

    [include voice_cues/voice_cues.cfg]

    You also need a [save_variables] section if you do not have one — the audio level and volume persist there:

    [save_variables]
    filename: ~/printer_data/config/variables.cfg
  5. FIRMWARE_RESTART, then run VOICE_TEST.


Using it

Add one line wherever something worth announcing happens:

[gcode_macro PRINT_END]
gcode:
    ...
    PLAY_AUDIO FILE=print_completed

For things that need you, mark the class:

    PLAY_AUDIO FILE=filament_not_detected CLASS=important TONE=error

CLASS=important survives the IMPORTANT level and becomes a tone under TONES. Everything else is routine and goes quiet as soon as the user turns the verbosity down.

docs/INTEGRATION.md has copy-paste blocks for the usual macros — PRINT_START, PRINT_END, PAUSE, RESUME, CANCEL_PRINT, runout handlers, filament load and unload.

Verbosity

Level Routine Important
TALKATIVE speaks speaks
IMPORTANT silent speaks
TONES silent short tone
MUTE silent silent
AUDIO_LEVEL LEVEL=IMPORTANT

Or the buttons AUDIO_TALKATIVE / AUDIO_IMPORTANT / AUDIO_TONES / AUDIO_MUTE, which appear in KlipperScreen's macro panel. The setting persists.

Anything unmarked is routine, so a new announcement is quiet-by-default and has to earn its way up. That is the safe direction: a printer that talks constantly is one you stop listening to, and then the runout announcement is worth nothing.

Volume

SET_SOUND_VOLUME VOLUME=70

For a slider in KlipperScreen (Pins panel) and Mainsail (Miscellaneous), uncomment the [output_pin sound_volume] block in voice_cues.cfg and give it a free pin on your board. Details and pin-choosing advice are in that file's comments.


The clips

33 files, 44.1 kHz mono 16-bit PCM.

Printprint_started print_completed print_paused print_resumed print_canceled operation_aborted soak_complete

Filamentloading_filament unloading_filament filament_loaded filament_detected filament_not_detected filament_unload_failed wrong_filament not_enough_filament

Calibrationstarting_bed_mesh bed_mesh_complete doing_z_tilt z_tilt_complete touch_z_probing touch_z_complete calibration_success homing_failed probe_failed mesh_failed

Othernozzle_change_complete warning critical_error

Tonesbeep_info beep_success beep_warning beep_error beep_critical

Making your own, including matching the voice of the existing set: docs/GENERATING.md.

Don't like the voice?

samples/ has the same line in twelve voices — six male, six female, US and GB — processed through the identical pipeline, so what you hear is what your printer would say. Listen first, then download only the model you want.

Swapping is a two-line edit in tools/make_sounds.py and one command. The high-tier models are the ones worth having: generation happens on a workstation, so the larger download costs you nothing ongoing.


Troubleshooting

Symptom Cause
Printer pauses when a clip plays A shell command is calling aplay directly. Route it through play_sound.sh.
First word cut off Lead-in buffer too short for your device — increase LEAD_MS in tools/process_sounds.py and reprocess. See §2 above.
Nothing at all aplay -L for the right device name; test by hand; check /tmp/klipper_audio.log.
Too quiet at 100% The mixer cannot exceed 0 dB. Reprocess louder — see docs/GENERATING.md.
Slider does nothing below ~70% You removed the square-root curve in _APPLY_VOLUME. The scale is dB.
Unknown command: RUN_SHELL_COMMAND gcode_shell_command is not installed.
Clips overlap or drop flock missing. apt install util-linux.

Credits

Built for a Voron Trident running Klipper + Moonraker with a BTT HDMI display. Speech generated with piper.

Contributions welcome — especially clips in other languages and voices, and confirmations of which ALSA_DEVICE value works on other hardware.

About

Spoken status announcements for Klipper, without stalling the printer. 33 clips, four verbosity levels, volume slider, and stdlib-only tooling to generate your own.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages