linux_tts 0.1.0 copy "linux_tts: ^0.1.0" to clipboard
linux_tts: ^0.1.0 copied to clipboard

Offline, on-device text-to-speech for embedded Linux via spd-say (speech-dispatcher). Pure Dart, no Flutter dependency. Degrades silently when the speech backend is absent.

linux_tts #

Offline, on-device text-to-speech for embedded Linux, in pure Dart with no Flutter dependency.

linux_tts wraps spd-say (the speech-dispatcher command-line client) behind a small TtsEngine abstraction. Speech synthesis happens entirely on-device through speech-dispatcher's local backend (e.g. eSpeak-NG), so it keeps working when there is no network and no GPS — the scenario it was built for: a driver in unexpected snow when the screen can no longer be relied on and the audio channel is the one that survives.

Advisory only. This package announces; it does not actuate. Do not wire it as a safety-actuator or treat its output as a control-class signal.

Provenance #

Extracted from the voice_guidance package of SNGNav (aki1770-del), where the same LinuxTtsEngine drives in-vehicle voice guidance in production. This is an extraction of proven, dogfooded code, not a greenfield rewrite.

The source voice_guidance package is BSD-3-Clause (copyright "Snow Guard Nav Contributors"); linux_tts is published under MIT. Both the SNGNav source and this extraction are authored solely by Akihiko Komada (aki1770-del), who as sole copyright holder relicenses this extracted subset under MIT.

Prior art in the same niche: dart_speechd (the-byte-bender, MPL-2.0) provides lower-level Dart bindings to speech-dispatcher. linux_tts does not depend on or copy it — it ships SNGNav's own subprocess-based engine — but acknowledges it as fellow-weaver prior work.

Install #

dependencies:
  linux_tts: ^0.1.0

Native dependency #

pub.flutter-io.cn ships Dart code, not native binaries. linux_tts shells out to spd-say, so the target must have speech-dispatcher installed and its daemon reachable, plus a synthesis backend (eSpeak-NG is the common default).

Debian / Ubuntu:

sudo apt install speech-dispatcher espeak-ng

Fedora:

sudo dnf install speech-dispatcher espeak-ng

Yocto / Buildroot (embedded images): add the speechd (speech-dispatcher) and espeak-ng recipes/packages to the image. Ensure the daemon can start under the image's init system; on locked-down or read-only-rootfs images verify speech-dispatcher's socket/runtime-dir assumptions hold.

If spd-say is absent the engine degrades silently (speak/stop become no-ops) — a missing daemon never crashes the consuming UI. Callers that require speech should detect capability up front (below).

Usage #

import 'package:linux_tts/linux_tts.dart';

Future<void> main() async {
  final TtsEngine engine = LinuxTtsEngine();

  // Capability detection — never assume the backend is present.
  if (!await engine.isAvailable()) {
    // Degrade gracefully, or fail loudly if speech is required:
    // (engine as LinuxTtsEngine).ensureAvailable() throws
    // TtsUnavailableException with remediation text.
    return;
  }

  await engine.setLanguage('ja-JP');
  await engine.setVolume(0.8);
  await engine.setSpeechRate(0.9); // slightly slower for an older driver
  await engine.speak('まもなく右折です。');

  // Cancel a stale prompt the instant conditions change:
  await engine.stop();

  await engine.dispose();
}

Failing loudly when speech is required #

For a life-critical audio channel (e.g. a vision-impaired driver), silent degradation is not acceptable. Use ensureAvailable():

final engine = LinuxTtsEngine();
try {
  await engine.ensureAvailable(); // throws TtsUnavailableException if absent
} on TtsUnavailableException catch (e) {
  // e.message carries remediation guidance (apt install ...).
}

Engines #

Engine Platform Behavior
LinuxTtsEngine Linux (dart:io) Speaks via spd-say; degrades to silent if absent.
NoOpTtsEngine Any Records spokenTexts; produces no audio. Test double.
LinuxTtsEngine Non-dart:io (e.g. web) Conditional export resolves to a silent NoOp.

Japanese #

spd-say with the eSpeak-NG backend supports Japanese (setLanguage('ja-JP'), normalized internally to ja). On a machine with speech-dispatcher + eSpeak-NG, spd-say -L lists Japanese voices, so capability is real.

Quality caveat: eSpeak-NG Japanese is a formant/dictionary synthesizer — intelligible but robotic, and kanji-heavy road names (県道/国道, place names) are NEEDS-VERIFICATION by listening test before any "production Japanese" claim. speech-dispatcher is backend-swappable: an integrator can route to a higher-quality module (e.g. Open JTalk) without changing this package's API.

Testing without a daemon #

The engine's Process.run / Process.start / executable-resolver hooks are injectable, so the unit suite runs in CI with no speech-dispatcher daemon:

final engine = LinuxTtsEngine(
  resolveExecutable: (_) => '/usr/bin/spd-say',
  startProcess: (exe, args) async { /* record + return a fake Process */ },
  runProcess: (exe, args) async => ProcessResult(0, 0, '', ''),
);

See test/ for the full pattern.

License #

MIT. The native dependencies it talks to (speech-dispatcher libspeechd LGPL-2.1+, the speechd daemon, eSpeak-NG GPL-3+) are installed by the integrator as separate system components — this Dart package does not link or relicense them, it shells out to spd-say across a process boundary.

0
likes
160
points
8
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Offline, on-device text-to-speech for embedded Linux via spd-say (speech-dispatcher). Pure Dart, no Flutter dependency. Degrades silently when the speech backend is absent.

Repository (GitHub)
View/report issues

Topics

#tts #speech #accessibility #linux #embedded

License

MIT (license)

More

Packages that depend on linux_tts