{"id":34052109,"url":"https://github.com/drien/tts-joinery","last_synced_at":"2026-03-17T20:13:51.463Z","repository":{"id":253430886,"uuid":"816321712","full_name":"drien/tts-joinery","owner":"drien","description":"Stitch together text-to-speech over 4096 characters via the OpenAI API","archived":false,"fork":false,"pushed_at":"2025-03-20T19:07:35.000Z","size":57,"stargazers_count":17,"open_issues_count":2,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-02T15:55:20.594Z","etag":null,"topics":["cli","openai","python","text-to-speech","tts"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/tts-joinery/","language":"Python","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/drien.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-17T13:59:45.000Z","updated_at":"2025-11-11T16:47:44.000Z","dependencies_parsed_at":"2024-08-16T17:43:53.065Z","dependency_job_id":"22eedc4f-fc0b-4605-9f66-d158511a8043","html_url":"https://github.com/drien/tts-joinery","commit_stats":null,"previous_names":["drien/tts-joinery"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/drien/tts-joinery","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drien%2Ftts-joinery","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drien%2Ftts-joinery/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drien%2Ftts-joinery/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drien%2Ftts-joinery/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drien","download_url":"https://codeload.github.com/drien/tts-joinery/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drien%2Ftts-joinery/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30630318,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-17T17:32:55.572Z","status":"ssl_error","status_checked_at":"2026-03-17T17:32:38.732Z","response_time":56,"last_error":"SSL_read: 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","openai","python","text-to-speech","tts"],"created_at":"2025-12-14T01:56:03.056Z","updated_at":"2026-03-17T20:13:51.458Z","avatar_url":"https://github.com/drien.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tts-joinery\n\ntts-joinery is a Python library and CLI tool to work around length limitations in text-to-speech APIs.\n\nSince currently-popular APIs are limited to 4096 characters, this library will:\n\n-   Chunk the input text into sentences using the [NLTK Punkt module](https://www.nltk.org/api/nltk.tokenize.punkt.html) (for better audio by avoiding segments split in the middle of a word or sentence).\n-   Run each chunk through the TTS API\n-   Join together the resulting output to produce a single MP3 file\n\nCurrently only the OpenAI API is supported, with the intent to add more in the future.\n\n## Installation\n\n```bash\npip install tts-joinery\n```\n\nor use `pipx` to install as a standalone tool.\n\n**Requires ffmpeg** for the audio file processing.\n\nInstallation may vary depending on your system. On Linux you can use your system package manager. On Mac `brew install ffmpeg` should work.\n\n## Usage\n\n### Command-Line Interface (CLI)\n\nThe CLI expects to find an OpenAI API Key in a `OPENAI_API_KEY` environment variable, or in a .env file.\n\n#### Syntax\n\n```\nttsjoin [OPTIONS] [COMMAND]\n```\n\n#### Options\n\n```\nOptions:\n--input-file FILENAME   Plaintext file to process into speech, otherwise stdin\n--output-file FILENAME  MP3 result, otherwise stdout\n--model TEXT            Slug of the text-to-speech model to be used (tts-1, tts-1-hd or gpt-4o-mini-tts)\n--service TEXT          API service (currently only supports openai)\n--voice TEXT            Slug of the voice to be used\n--instructions TEXT     Voice instructions (only for gpt-4o-mini-tts model)\n--no-cache BOOLEAN      Disable caching\n--help                  Show this message and exit.\n\nCommands:\n  cache [clear, show]\n```\n\n#### Examples\n\n1. Using an input file and specifying an output file:\n\n```bash\n# Basic usage with tts-1 model\nttsjoin --input-file input.txt --output-file output.mp3 --model tts-1 --service openai --voice onyx\n\n# Using the new gpt-4o-mini-tts model with instructions\nttsjoin --input-file input.txt --output-file output.mp3 --model gpt-4o-mini-tts --voice ballad --instructions \"Speak in a calm, soothing voice\"\n```\n\n2. Using stdin and stdout with default options:\n\n```bash\necho \"Your text to be processed\" | ttsjoin \u003e output.mp3\n```\n\n3. Each chunk of text is cached for performance when running the same text multiple times, this can be disabled:\n\n```bash\nttsjoin --input-file input.txt --output-file output.mp3 --no-cache\n```\n\n5. Clear cache directory\n\n```bash\nttsjoin cache clear\n```\n\n### Python Library\n\nYou can also use tts-joinery as part of your Python project:\n\n```python\nimport nltk\n\nfrom joinery.op import JoinOp\nfrom joinery.api.openai import OpenAIApi\n\n# Only need to download once, handled for you automatically in the CLI\nnltk.download('punkt_tab', quiet=True)\n\ntts = JoinOp(\n    text='This is only a test!',\n    api=OpenAIApi(\n        model='tts-1-hd',  # or 'gpt-4o-mini-tts' for the new model\n        voice='onyx',\n        api_key=OPENAI_API_KEY,\n        instructions='Speak in a calm, soothing voice',  # Optional, only for gpt-4o-mini-tts\n    ),\n)\n\ntts.process_to_file('output.mp3')\n```\n\n## Changelog\n\n#### v1.0.5 (2025-03-20)\n\n-   Added support for OpenAI's gpt-4o-mini-tts model and `instructions` parameter\n\n#### v1.0.4 (2024-10-11)\n\n-   Fixed issue with nltk dependency [#4](https://github.com/drien/tts-joinery/issues/5)\n-   Model, voice, and service CLI params are now case-insensitive\n\n#### v1.0.3 (2024-10-05)\n\n-   Added cache management commands to cli\n-   Fixed a bug when running\n-   Added end-to-end tests\n\n#### v1.0.2 (2024-10-03)\n\n-   Fixed crash when running with caching disabled (#3)\n\n## Contributing\n\nContributions welcome, particularly other TTS APIs, check the issues beforehand and feel free to open a PR. Code is formatted with Black.\n\nTest can be run manually. Suite includes end-to-end tests with live API calls, ensure you have an OPENAI_API_KEY set in `.env.test`, and run `pytest`. You can install development dependencies with `pip install -e .[test]`\n\n## Contributors\n\nSpecial thanks to:\n\n-   [Mayank Vishwakarma](mailto:mayank@mynk.me) (@mayankwebbing)\n\n## License\n\nThis project is licensed under the MIT License.\n\nCopyright 2024, Adrien Delessert\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrien%2Ftts-joinery","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrien%2Ftts-joinery","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrien%2Ftts-joinery/lists"}