Powered speakers switch themselves off after a few minutes of silence, and then swallow the first second or two of whatever you play next — the start of a video, the first word of a call, the beginning of a notification sound.
Da Keep Speakers Alive keeps them awake by sending them a short tone so low and so quiet that you cannot hear it, once every few minutes.
Windows · Czech and English interface · Apache 2.0
There are other programs for this, and the best of them is vrubleg/SoundKeeper — mature, tiny, written in C++, and it also handles analog outputs. If it does what you need, use it. This project exists because of two things it does not do:
| SoundKeeper | Da Keep Speakers Alive | |
|---|---|---|
| Settings | by renaming the .exe | a normal window |
| Which output the pulse goes to | the default one | any outputs you pick, one or several |
| The signal | a continuous tone | a 0.4 s burst every few minutes |
| Language | — | Czech / English |
The burst instead of a continuous tone is the deliberate part. Modern Standby (the sleep mode of every current Windows laptop) keeps the machine partly awake while an audio stream is open, so a program that holds one open all day is not free. Here the stream exists for 0.4 seconds out of every 180 — the smallest thing that still does the job.
Picking the output matters as soon as a machine has more than one — and a laptop on a dock, with a monitor and a USB audio interface attached, easily has four. Usually only one of them falls asleep, and there is no reason to send anything to the rest. You can also tick several at once, or follow the system default and pick extra outputs on top of it.
A sine burst with soft edges — 20 Hz, 1 % of full scale (−40 dBFS), 0.4 s, every 3 minutes by default.
The defaults come from measurement rather than guesswork: at 20 Hz and 1 % the burst was inaudible in a quiet room, while half that level was already enough to keep the speakers from switching off. The shipped default is the louder of the two, because headroom you cannot hear costs nothing.
Everything is adjustable in the window: 5–100 Hz, 0.1–10 %, 0.1–2 s, every 30 s to 15 minutes. Three details are worth knowing before you turn the knobs:
- The edges are faded in and out. Without that, the burst starts and ends on a step, and a step is broadband noise — a click you hear far better than the tone itself.
- A burst shorter than two full waves is not a tone, it is a DC step that the speaker's coupling capacitor eats. The window warns you when your combination of frequency and length falls under that line.
- The audio buffer is the app's own, 100 ms, drained before the stream is closed. Left to WASAPI's shared-mode default it came out at 22 ms, and a buffer that short crackles the whole way through the pulse — at any volume and any frequency, on hardware that plays music perfectly well.
If you can hear the pulse, lower the volume first — then the frequency. Low tones at a high setting ask more of a small speaker than it can give.
An icon next to the clock, and a settings window behind it.
- Which speakers to keep awake — the system default output, or outputs you pick by hand, or both. A device is remembered by name, not by index, so the choice survives replugging the USB into another port. One that is not currently connected stays in the list, marked as such.
- How often — 30 s to 15 minutes.
- What the pulse sounds like — frequency, length, volume, plus a Try a pulse button with a progress bar. The bar exists because the pulse is inaudible on purpose: without it, a working app and a broken one look exactly the same.
- Dynamic volume correction — optional. Windows attenuates the pulse just as it attenuates music, so with the volume slider low the speaker may never notice it (measured: a slider at 4 % is −31.7 dB, which turns a 1 % pulse into 0.026 % of full scale). Switched on, the app puts back exactly what Windows takes off — never more, so a pulse you cannot hear at full volume stays one you cannot hear.
- Start when I log in to Windows — registers a task in Task Scheduler.
- Links at the foot — the manual, the log, the project page, and a check
for updates that opens the releases page rather than asking the network by
itself. The log is always written: some 28 kB a day, and never past 4 MB,
because rotation keeps two files of two. There is no switch for it, because
it is the only record of what the app did in the moments nobody can
reproduce — a sleep, an unplugged dock, a mute.
"log": falseinconfig.jsonstill turns it off. - Pause for a while — for when you need real silence, recording audio, say. It switches itself back on afterwards.
- Czech / English, switched live by the two flags in the top right corner.
It cannot be a Windows service. Services run in session 0, where audio does not physically play. It has to be a normal user process — which also means a locked screen or a blanked monitor changes nothing, because neither ends your session.
It does not keep the computer awake, and it cannot wake it up. A running process has nothing to wake anything with: in hibernation it does not exist, and under Modern Standby Windows freezes it. After the machine wakes up, the pulse goes out straight away rather than at the end of the interval — the speakers slept through it too. The same at logon, and the same the moment a chosen speaker becomes reachable again: you plug it in, or you un-mute it in Windows (volume back off zero counts too). Both used to buy silence for up to a whole interval — a muted output accepts the pulse and plays nothing at all. And if the pulse cannot be played because the device has yet to come back, it is retried within seconds instead of one interval later.
Wherever the audio path itself has just come up — a start, a wake-up, a speaker being plugged in — one pulse is not the end of it: it repeats for the first minute, every fifteen seconds. A pulse can land while the device is still starting, where it plays into nothing and is reported as sent all the same, and a path that is still waking up can swallow more than one of them. None of them is audible, it can be switched off, and every pulse in the log carries how long the device took to open and to write — because a pulse recorded as sent is not proof that anything was heard.
Download DaKeepSpeakersAlive-setup.exe from
Releases
and run it. It asks for administrator rights, installs into
C:\Program Files\Da Keep Speakers Alive, and can set up the shortcuts and
starting at logon. It speaks Czech and English — click a flag in the top right
corner. Removing it later works from Settings → Apps, the ordinary way.
The installer is not signed, so SmartScreen will warn on first run (More info → Run anyway).
Or run it from source:
py -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
start.bat # the icon appears next to the clock
start.bat --show # and open the window right awayNeeds Python 3.14 and Windows. The dependencies are sounddevice (PortAudio,
WASAPI), numpy, pystray and Pillow; tkinter comes with Python.
Run from source, the settings and the log sit next to the sources. An installed
copy will put them in %APPDATA%\Da Keep Speakers Alive instead.
Other switches: --pulse sends one pulse and quits, --autostart-on /
--autostart-off are for the installer.
Full instructions: English manual · česky
windows\keep_alive.py the whole app: engine, tray icon, settings window
windows\texts.py every text, Czech and English side by side
windows\marks.py hand-drawn checkboxes and language flags (the Tk ones
are tiny) - shared by the app AND the installer
installer\installer.py installer and uninstaller in one program
installer\build_installer.ps1 packs both with PyInstaller
tools\tune.py measuring: --list, --tone, --keepalive, --check
tests\ see below
Before any release:
.venv\Scripts\python.exe tests\test_logic.py the pulse, devices, texts, settings file
.venv\Scripts\python.exe tests\test_window.py branches normal use never reaches
.venv\Scripts\python.exe tests\test_installer.py the whole install/uninstall cycle
.venv\Scripts\python.exe tests\preview.py renders the window to PNG - then look at it
.venv\Scripts\python.exe tests\preview.py --installer the same for the setup windowstest_installer.py redirects every target into %TEMP% and an HKCU key, so
it needs no administrator and never touches a real installation. It refuses to
run while the app is up — it stops whatever holds the app's lock, and that
would be your own copy.
Both test files carry their own counter-cases: every check comes with a case
that must make it complain, because a check nobody ever tried to break reads
exactly like a check that does not work. test_window.py --break-it puts five
real, previously-shipped bugs back in and the run has to fail.
tools\tune.py is the measuring rig the defaults came out of — it lists the
outputs, plays a single tone so you can tell whether you hear it, runs a
keep-alive cycle for as long as you like, and plays a series of audible beeps
to check whether the speakers dropped any.
- Windows only. WASAPI, Task Scheduler and the tray icon are all Windows-specific.
- Inaudible is not guaranteed. It depends on your speakers and your room. If you can hear it, lower the volume or the frequency — that is what the settings are for.
- The installer is unsigned, so SmartScreen warns on first run. Signing means a paid certificate.
- Three minutes is known to be enough, not known to be the maximum. Longer intervals were never tested.
Apache License 2.0 — see LICENSE.