{"id":49083534,"url":"https://github.com/ppikrorngarn/ttscli","last_synced_at":"2026-04-20T14:06:00.491Z","repository":{"id":352619437,"uuid":"1215209426","full_name":"ppikrorngarn/ttscli","owner":"ppikrorngarn","description":"A lightweight Go CLI for text-to-speech. Google Cloud ready, more providers coming soon. Play instantly or save as MP3. Cross-platform, profile-based config.","archived":false,"fork":false,"pushed_at":"2026-04-20T12:19:41.000Z","size":139,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T13:33:27.822Z","etag":null,"topics":["cli","command-line","cross-platform","go","golang","google-cloud","mp3","speech-synthesis","text-to-speech","tts"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ppikrorngarn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-19T16:14:40.000Z","updated_at":"2026-04-20T12:17:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ppikrorngarn/ttscli","commit_stats":null,"previous_names":["ppikrorngarn/ttscli"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ppikrorngarn/ttscli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppikrorngarn%2Fttscli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppikrorngarn%2Fttscli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppikrorngarn%2Fttscli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppikrorngarn%2Fttscli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ppikrorngarn","download_url":"https://codeload.github.com/ppikrorngarn/ttscli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppikrorngarn%2Fttscli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32050454,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-20T11:35:06.609Z","status":"ssl_error","status_checked_at":"2026-04-20T11:34:48.899Z","response_time":94,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line","cross-platform","go","golang","google-cloud","mp3","speech-synthesis","text-to-speech","tts"],"created_at":"2026-04-20T14:05:59.812Z","updated_at":"2026-04-20T14:06:00.476Z","avatar_url":"https://github.com/ppikrorngarn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Multi-Provider Text-to-Speech CLI (`ttscli`)\n\n[![CI](https://github.com/ppikrorngarn/ttscli/actions/workflows/ci.yml/badge.svg)](https://github.com/ppikrorngarn/ttscli/actions/workflows/ci.yml)\n[![Go Reference](https://pkg.go.dev/badge/github.com/ppikrorngarn/ttscli.svg)](https://pkg.go.dev/github.com/ppikrorngarn/ttscli)\n[![License](https://img.shields.io/github/license/ppikrorngarn/ttscli)](LICENSE)\n[![Latest Release](https://img.shields.io/github/v/release/ppikrorngarn/ttscli)](https://github.com/ppikrorngarn/ttscli/releases/latest)\n\nA lightweight, fast Command Line Interface (CLI) written in Go to convert text into speech using multiple cloud TTS providers. Currently supports Google Cloud, with planned support for AWS, Azure, IBM Cloud, and Alibaba Cloud.\n\nThis tool allows you to easily synthesize speech, save it to an MP3 file, or play it directly from your terminal on macOS, Linux, and Windows.\n\n## Privacy\n\n`ttscli` makes no network calls except to the TTS provider you configure (e.g., Google Cloud Text-to-Speech). No telemetry, no analytics, no phone-home. Your API key never leaves your machine except in requests to the provider's API endpoint.\n\n## Prerequisites\n\n1. **Go:** Install Go `1.25+` (matches `go.mod`).\n2. **Cloud Provider API Key:** You need an API key for your chosen TTS provider.\n   - **Google Cloud:** Go to Google Cloud Console \u003e APIs \u0026 Services \u003e Credentials. Create an API Key and restrict it to the \"Cloud Text-to-Speech API\".\n   - **Other providers:** Support coming soon.\n3. **Audio Player (Linux and Windows):** The `speak` command plays MP3 audio and needs an external player. macOS ships with `afplay` by default, so no install is needed there.\n   - **Linux:** install one of `mpg123`, `paplay`, or `ffplay`.\n     - Ubuntu/Debian: `sudo apt install mpg123`\n   - **Windows:** install one of `mpg123` or `ffplay` (ships with [ffmpeg](https://ffmpeg.org/)) and make sure the binary is on your `Path`.\n     - Scoop: `scoop install ffmpeg` or `scoop install mpg123`\n     - Chocolatey: `choco install ffmpeg` or `choco install mpg123`\n4. **Staticcheck (for local quality checks):** Optional but recommended for contributors.\n   - Install: `go install honnef.co/go/tools/cmd/staticcheck@v0.7.0`\n\n## Setup\n\n1. **Install the CLI:**\n   ```bash\n   go install github.com/ppikrorngarn/ttscli/cmd/ttscli@latest\n   ```\n   This installs the `ttscli` binary into your Go bin directory.\n   If `GOBIN` is set, Go installs there. Otherwise it uses:\n   ```bash\n   $(go env GOPATH)/bin\n   ```\n\n   You can inspect `GOBIN` with:\n   ```bash\n   $(go env GOBIN)\n   ```\n\n   Make sure that directory is in your `PATH`.\n\n   Use the same Go bin directory in your `PATH`.\n   If `GOBIN` is empty, that usually means `$(go env GOPATH)/bin`.\n\n   Temporary shell setup for the current session:\n   ```bash\n   export PATH=\"\u003cgo-bin-dir\u003e:$PATH\"\n   ```\n\n   To make that permanent on macOS/Linux, add the same line to your shell profile such as `~/.zshrc`, `~/.bashrc`, or `~/.profile`.\n\n   Temporary PowerShell example for the current session:\n   ```powershell\n   $env:Path += \";\u003cgo-bin-dir\u003e\"\n   ```\n\n   To make that permanent on Windows, add the directory to your user `Path` environment variable in System Settings, or persist it in your PowerShell profile.\n\n   Then verify the install:\n   ```bash\n   ttscli --version\n   ```\n\n2. **Or download a pre-built binary from GitHub Releases:**\n\n   Each tagged release (matching `v*.*.*`) produces archives built by GoReleaser. The following combinations are published:\n\n   | OS      | Architectures | Archive format |\n   |---------|---------------|----------------|\n   | Linux   | amd64, arm64  | `.tar.gz`      |\n   | macOS   | amd64, arm64  | `.tar.gz`      |\n   | Windows | amd64, arm64  | `.zip`         |\n\n   A `checksums.txt` file is published alongside each release for verification. Extract the archive, place the `ttscli` binary somewhere on your `PATH`, and verify with `ttscli --version`.\n\n3. **Or clone the repository and build the binary locally:**\n   You can use the provided Makefile to build the project easily:\n   ```bash\n   make build\n   ```\n   *(Or run `go build -o ttscli ./cmd/ttscli` directly).*\n\n   If you want to install that locally built binary into your personal bin directory:\n   ```bash\n   mkdir -p ~/.local/bin\n   install -m 0755 ttscli ~/.local/bin/ttscli\n   export PATH=\"$HOME/.local/bin:$PATH\"\n   ```\n\n   The `export PATH=...` line only affects the current shell session.\n   To make it permanent on macOS/Linux, add it to your shell profile such as `~/.zshrc`, `~/.bashrc`, or `~/.profile`.\n\n   Windows PowerShell example:\n   ```powershell\n   New-Item -ItemType Directory -Force \"$HOME\\bin\" | Out-Null\n   Copy-Item .\\ttscli.exe \"$HOME\\bin\\ttscli.exe\"\n   $env:Path += \";\" + \"$HOME\\bin\"\n   ```\n\n   The `$env:Path += ...` line only affects the current PowerShell session.\n   To make it permanent on Windows, add `%USERPROFILE%\\bin` to your user `Path` environment variable in System Settings, or persist it in your PowerShell profile.\n\n   Then verify it:\n   ```bash\n   ttscli --version\n   ```\n\n4. **Run first-time setup (recommended):**\n   ```bash\n   ttscli setup\n   ```\n    This guided flow prompts for API key, default language, and default voice, validates them, and can run a sound check.\n    Press Enter on language/voice prompts to use built-in defaults: `en-US` and `en-US-Neural2-F`.\n    **Note:** The API key input is masked (hidden) as you type or paste for security.\n\n### Contributor Setup\n\nFor local quality checks:\n\n```bash\nmake tools\nexport PATH=\"\u003cgo-bin-dir\u003e:$PATH\"\nmake check\n```\n\nUse the same Go bin directory that `go install` writes to.\nIf `GOBIN` is empty, that usually means `$(go env GOPATH)/bin`.\n\nThe `export PATH=...` line above only affects the current shell session.\nIf you use these tools often, add the same line to your shell profile.\n\nFor contribution and licensing details, see:\n- [CONTRIBUTING.md](./CONTRIBUTING.md)\n- [LICENSE](./LICENSE)\n\n### Development Checks\n\nThe `Makefile` provides the following targets:\n\n| Target           | Description                                                       |\n|------------------|-------------------------------------------------------------------|\n| `make build`     | Build the `ttscli` binary with version metadata injected via ldflags |\n| `make clean`     | Remove the compiled binary and any `*.mp3` files                 |\n| `make run`       | Build and run the CLI (pass flags via `ARGS=\"...\"`)              |\n| `make test`      | Run all tests with verbose output                                |\n| `make test-race` | Run all tests with the race detector                             |\n| `make tools`     | Install local developer tools (staticcheck)                      |\n| `make lint`      | Run static analysis (staticcheck)                                |\n| `make check`     | Run `go vet`, tests, race tests, and lint                        |\n| `make help`      | Print all available targets with their descriptions              |\n\nQuick examples:\n\n```bash\nmake build\nmake run ARGS=\"--version\"\nmake check\n```\n\n## Usage\n\nIf you installed via `go install`, run `ttscli ...` from your shell `PATH`.\nIf you built locally with `make build`, run `./ttscli ...` from the repo root.\nIf you manually copied the binary into a personal bin directory such as `~/.local/bin`, run `ttscli ...` after adding that directory to your `PATH`.\nOn Windows, the equivalent is typically `ttscli.exe` from a directory such as `%USERPROFILE%\\bin` after adding it to `Path`.\n\n### Profile System\n\n`ttscli` uses a profile-based configuration system that allows you to manage multiple TTS provider configurations. Each profile contains:\n\n- **Provider**: The TTS service provider (e.g., `gcp`, `aws`, `azure`)\n- **Name**: A unique name for the profile (e.g., `default`, `work`, `personal`)\n- **Credentials**: Provider-specific authentication (e.g., API keys)\n- **Defaults**: Default language and voice settings for that profile\n\n**Profile Key Format**: `{provider}:{name}` (e.g., `gcp:default`, `aws:work`)\n\n**Profile Resolution**:\n1. `--profile` flag\n2. Active profile from config\n3. Error if no active profile is set\n\n**Current Provider Support**:\n- ✅ **Google Cloud (GCP)**: Fully implemented\n- 🚧 **AWS Polly**: Planned\n- 🚧 **Azure Speech**: Planned\n- 🚧 **IBM Watson**: Planned\n- 🚧 **Alibaba Cloud**: Planned\n\n### Configuration File\n\n`ttscli` stores its profiles in a JSON file. The CLI resolves the config path in two steps:\n\n1. **Next to the binary** — if a `config.json` sits in the same directory as the `ttscli` executable, it takes priority. Useful for portable or pinned setups.\n2. **User config directory (fallback):**\n\n| OS      | Path                                                 |\n|---------|------------------------------------------------------|\n| macOS   | `~/Library/Application Support/ttscli/config.json`   |\n| Linux   | `~/.config/ttscli/config.json`                       |\n| Windows | `%AppData%\\ttscli\\config.json`                       |\n\n**Config file format:**\n\n```json\n{\n  \"activeProvider\": \"gcp\",\n  \"activeProfile\": \"default\",\n  \"profiles\": {\n    \"gcp:default\": {\n      \"provider\": \"gcp\",\n      \"name\": \"default\",\n      \"credentials\": {\n        \"apiKey\": \"YOUR_API_KEY\"\n      },\n      \"defaults\": {\n        \"lang\": \"en-US\",\n        \"voice\": \"en-US-Neural2-F\"\n      }\n    }\n  }\n}\n```\n\nPrefer managing profiles via the `ttscli profile` subcommands (see [Command Reference](#command-reference)) rather than editing this file by hand.\n\n\n### Command Reference\n\n- `ttscli speak`: Synthesize text to speech and play it immediately.\n- `ttscli save`: Synthesize text to speech and save MP3 output.\n- `ttscli voices`: List available voices (optionally filter with `--lang`).\n- `ttscli setup`: Interactive first-run setup (creates a GCP profile).\n- `ttscli doctor`: Health checks (config, profiles, API connectivity, playback). Returns non-zero when checks fail.\n- `ttscli completion \u003cbash|zsh|fish\u003e`: Prints shell completion script to stdout.\n- `ttscli profile list`: List all configured profiles.\n- `ttscli profile create`: Create a new profile with provider credentials.\n- `ttscli profile delete \u003cprovider:name\u003e`: Delete a profile.\n- `ttscli profile use \u003cprovider:name\u003e`: Set the active profile.\n- `ttscli profile get \u003cprovider:name\u003e`: Show profile details.\n- `ttscli --version`: Print build metadata.\n- `ttscli --help`: Show top-level help.\n\n### `speak` Flags\n\n| Flag | Type | Default | Notes |\n| --- | --- | --- | --- |\n| `--text` | string | `\"\"` | Required for `speak`. Alias: `-t`. |\n| `--lang` | string | `en-US` | Language code for speak (or profile default). Alias: `-l`. |\n| `--voice` | string | `en-US-Neural2-F` | Voice name for synth (or profile default). Alias: `-v`. |\n| `--profile` | string | `\"\"` | Profile to use (e.g., `gcp:default`). Alias: `-p`. |\n\n### `save` Flags\n\n| Flag | Type | Default | Notes |\n| --- | --- | --- | --- |\n| `--text` | string | `\"\"` | Required for `save`. Alias: `-t`. |\n| `--out` | string | `\"\"` | Required output MP3 path. Alias: `-o`. |\n| `--lang` | string | `en-US` | Language code for save (or profile default). Alias: `-l`. |\n| `--voice` | string | `en-US-Neural2-F` | Voice name for save (or profile default). Alias: `-v`. |\n| `--profile` | string | `\"\"` | Profile to use (e.g., `gcp:default`). Alias: `-p`. |\n\n### `voices` Flags\n\n| Flag | Type | Default | Notes |\n| --- | --- | --- | --- |\n| `--lang` | string | `en-US` | Optional language filter for voice listing. Alias: `-l`. |\n| `--profile` | string | `\"\"` | Profile to use (e.g., `gcp:default`). Alias: `-p`. |\n\n### `profile create` Flags\n\n| Flag | Type | Default | Notes |\n| --- | --- | --- | --- |\n| `--provider` | string | `\"\"` | Required. Provider name (e.g., `gcp`). Alias: `-P`. |\n| `--name` | string | `\"\"` | Required. Unique profile name (e.g., `default`, `work`). Alias: `-n`. |\n| `--api-key` | string | `\"\"` | Required. API key for the provider. Alias: `-k`. |\n| `--voice` | string | `\"\"` | Optional default voice to seed into the profile. Alias: `-v`. |\n\n### Basic Commands\n\n**0. Show CLI version/build metadata:**\n```bash\nttscli --version\n```\n\n**1. Run setup wizard (first run):**\n```bash\nttscli setup\n```\n\n**2. Run diagnostics:**\n```bash\nttscli doctor\n```\n\n**3. Manage profiles:**\n```bash\n# List all profiles\nttscli profile list\n\n# Create a new profile\nttscli profile create --provider gcp --name work --api-key YOUR_API_KEY\n\n# Create a profile with a default voice already set\nttscli profile create --provider gcp --name work --api-key YOUR_API_KEY --voice en-US-Neural2-F\n\n# Set active profile\nttscli profile use gcp:work\n\n# View profile details\nttscli profile get gcp:work\n\n# Delete a profile\nttscli profile delete gcp:work\n```\n\n**4. Generate shell completions:**\n```bash\nttscli completion zsh\n```\n\n**5. Play audio immediately (without saving):**\n```bash\n# Using active profile\nttscli speak --text \"Hello world, this is a test.\"\n\n# Using specific profile\nttscli speak --text \"Hello world, this is a test.\" --profile gcp:work\n```\n\n**6. Save audio to a file:**\n```bash\n# Using active profile\nttscli save --text \"Save this to a file.\" --out output.mp3\n\n# Using specific profile\nttscli save --text \"Save this to a file.\" --out output.mp3 --profile gcp:work\n```\n\n**7. List voices:**\n```bash\n# Using active profile\nttscli voices --lang en-GB\n\n# Using specific profile\nttscli voices --lang en-GB --profile gcp:work\n```\n\n### Alias Quick Examples\n\n```bash\nttscli speak -t \"Hello world, this is a test.\"\nttscli save -t \"Save this to a file.\" -o output.mp3\nttscli voices -l en-GB\n```\n\n### Voice and Language Selection\n\nBy default, the CLI uses a female US English voice (`en-US-Neural2-F`). You can customize this using the `--lang` and `--voice` flags.\n\n**Example: British Male Voice:**\n```bash\nttscli speak --text \"Hello there, how are you doing today?\" --lang \"en-GB\" --voice \"en-GB-Neural2-B\"\n```\n\n**Example: French Voice:**\n```bash\nttscli speak --text \"Bonjour le monde\" --lang \"fr-FR\" --voice \"fr-FR-Neural2-A\"\n```\n\n### Listing Available Voices\n\nYou can list all available voices for a specific language directly from the API.\n\n**List US English voices (default):**\n```bash\nttscli voices\n```\n\n**List voices for another language:**\n```bash\nttscli voices --lang en-GB\n```\n\n## Project Structure\n\nModule path: `github.com/ppikrorngarn/ttscli`\n\nThe codebase is organized into a thin `cmd/` entry point and focused `internal/` packages:\n\n```\ncmd/ttscli/          Binary entry point. Injects version/commit/date via ldflags at build time.\ninternal/cli/        Argument parsing. Owns the Config struct and all mode/subcommand constants.\ninternal/app/        Command handlers (setup, doctor, profile, completion). Orchestrates the run\n                     flow: parse args -\u003e resolve profile -\u003e create provider -\u003e execute.\ninternal/config/     JSON config file I/O. Profile CRUD. Two-step path resolution (local next\n                     to the binary, falling back to the user config directory).\ninternal/player/     Cross-platform audio playback. macOS: afplay. Linux: mpg123/paplay/ffplay.\n                     Windows: mpg123 or ffplay (requires install).\ninternal/tts/        Provider interface, GCP HTTP client, voice listing, PrintVoices helper.\n```\n\nPackages under `internal/` use small, package-level function variables (e.g. `readFile`, `writeFile`, `lookupEnv`) for dependency injection, so tests can stub the filesystem, environment, and HTTP calls without real I/O.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppikrorngarn%2Fttscli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fppikrorngarn%2Fttscli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppikrorngarn%2Fttscli/lists"}