Skip to content

Commit

Permalink
Merge pull request #4 from nateshmbhat/master
Browse files Browse the repository at this point in the history
update to master in upstream
  • Loading branch information
willwade authored Nov 14, 2024
2 parents 9aae58a + 43509f4 commit b27c315
Show file tree
Hide file tree
Showing 20 changed files with 478 additions and 86 deletions.
25 changes: 18 additions & 7 deletions .github/workflows/python_publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This workflows will upload a Python Package using Twine when a release is created.
# This workflow will upload a Python Package using Twine when a release is created.
# https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries
name: CI

Expand All @@ -24,17 +24,27 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
os: [macos-latest, ubuntu-latest, windows-latest]
python-version: ['3.9', '3.11', '3.13']
max-parallel: 9
runs-on: ${{ matrix.os }}
timeout-minutes: 10 # Save resources while our pytests are hanging
steps:
- if: runner.os == 'Linux'
run: sudo apt-get update -q -q && sudo apt-get install --yes espeak-ng libespeak1
- if: runner.os == 'macOS'
run: brew install espeak-ng
- name: Download and install eSpeak-NG
if: runner.os == 'Windows'
shell: pwsh
run: |
sudo apt-get update -q -q
sudo apt-get install --yes espeak-ng libespeak1
Invoke-WebRequest -Uri "https://github.com/espeak-ng/espeak-ng/releases/download/1.51/espeak-ng-X64.msi" -OutFile "espeak-ng.msi"
Start-Process msiexec.exe -ArgumentList '/i espeak-ng.msi /quiet /norestart' -Wait
# dir "$env:ProgramFiles\eSpeak NG"
$env:Path += ";$env:ProgramFiles\eSpeak NG"
espeak-ng --version
- if: runner.os != 'Windows'
run: espeak-ng --version

- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
Expand All @@ -43,10 +53,11 @@ jobs:
- name: Install dependencies
run: |
pip install --upgrade pip
pip install pytest pytest-timeout
pip install pytest
pip install --editable .
- run: pytest -s -vvv --timeout=600
- timeout-minutes: 10 # Save resources while our pytests are hanging
run: pytest -s -vvv --strict

build:
runs-on: ubuntu-latest
Expand Down
6 changes: 4 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ repos:
- tomli

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.7.2
rev: v0.7.3
hooks: # Format before linting
- id: ruff-format
- id: ruff
- id: ruff-format
args: [ --diff ]
- id: ruff-format
8 changes: 4 additions & 4 deletions MANIFEST
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# file GENERATED by distutils, do NOT edit
setup.cfg
setup.py
pyproject.toml
pyttsx3\__init__.py
pyttsx3\driver.py
pyttsx3\engine.py
pyttsx3\voice.py
pyttsx3\drivers\__init__.py
pyttsx3\drivers\_espeak.py
pyttsx3\drivers\avspeech.py
pyttsx3\drivers\dummy.py
pyttsx3\drivers\espeak.py
pyttsx3\drivers\nsss.py
pyttsx3\drivers\sapi5.py
pyttsx3\engine.py
pyttsx3\voice.py
25 changes: 18 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,24 @@ engine.runAndWait()

### **Full documentation of the Library**

https://pyttsx3.readthedocs.io/en/latest/

#### Included TTS engines:

* espeak
* nsss
* sapi5
https://pyttsx3.readthedocs.io

#### Included Text-To-Speech Engines by Operating System
| | Linux | macOS | Windows |
|-------------------------|:-----:|:-----:|:-------:|
| [AVSpeech][] | | ✅︎ | |
| [eSpeak][] | ✅︎ | ✅︎ | ✅︎ |
| [NSSpeechSynthesizer][] | | ✅︎ | |
| [SAPI5][] | | | ✅︎ |

> [!NOTE]
> * AVSpeechSynthesizer support is still experimental.
> * NSSpeechSynthesizer is deprecated by Apple.
[AVSpeech]: https://developer.apple.com/documentation/avfoundation/speech_synthesis
[eSpeak]: https://github.com/espeak-ng/espeak-ng?tab=readme-ov-file#readme
[NSSpeechSynthesizer]: https://developer.apple.com/documentation/appkit/nsspeechsynthesizer
[SAPI5]: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms723627(v=vs.85)

Feel free to wrap another text-to-speech engine for use with ``pyttsx3``.

Expand Down
1 change: 0 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# pyttsx3 documentation build configuration file, created by
# sphinx-quickstart on Sun Jun 25 11:19:31 2017.
Expand Down
5 changes: 3 additions & 2 deletions docs/engine.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ The Engine factory

:param driverName: Name of the :mod:`pyttsx3.drivers` module to load and use. Defaults to the best available driver for the platform, currently:

* `avspeech` - AVSynthesizer on macOS
* `espeak` - eSpeak on all platforms
* `nsss` - NSSpeechSynthesizer on macOS (Deprecated by Apple)
* `sapi5` - SAPI5 on Windows
* `nsss` - NSSpeechSynthesizer on Mac OS X
* `espeak` - eSpeak on every other platform

:param debug: Enable debug output or not.
:raises ImportError: When the requested driver is not found
Expand Down
20 changes: 11 additions & 9 deletions example/repeatvoice.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pyttsx3 # pyttsx3 is a text-to-speech conversion library in Python
import speech_recognition as s # Google Speech API in Python
# pip3 install SpeechRecognition
import speech_recognition # A speech-to-text conversion library in Python

# Functional programming Model
import pyttsx3 # A text-to-speech conversion library in Python


def text_to_speech(text):
Expand All @@ -14,11 +14,13 @@ def text_to_speech(text):


def speech_to_text():
r = s.Recognizer() # an object r which recognises the voice
with s.Microphone():
# when using with statement. The with statement itself ensures proper acquisition and release of resources
print(r.recognize_google(audio))
text_to_speech(r.recognize_google(audio))
recognizer = speech_recognition.Recognizer()
with speech_recognition.Microphone() as microphone:
audio = recognizer.listen(microphone)
text = recognizer.recognize_google(audio)
print(text)
text_to_speech(text)


speech_to_text()
if __name__ == "__main__":
speech_to_text()
1 change: 0 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,3 @@ include-package-data = false
[tool.ruff]
target-version = "py39"
line-length = 88
lint.extend-ignore = [ "F403", "F405", "F821" ]
3 changes: 2 additions & 1 deletion pyttsx3/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .engine import Engine
import weakref

from .engine import Engine

_activeEngines = weakref.WeakValueDictionary()


Expand Down
2 changes: 1 addition & 1 deletion pyttsx3/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import weakref


class DriverProxy(object):
class DriverProxy:
"""
Proxy to a driver implementation.
Expand Down
27 changes: 15 additions & 12 deletions pyttsx3/drivers/_espeak.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import print_function

import time
from ctypes import (
CFUNCTYPE,
Expand All @@ -20,7 +18,7 @@


def cfunc(name, dll, result, *args):
"""build and apply a ctypes prototype complete with parameter flags"""
"""Build and apply a ctypes prototype complete with parameter flags"""
atypes = []
aflags = []
for arg in args:
Expand All @@ -36,6 +34,7 @@ def load_library():
global dll
paths = [
# macOS paths
"/opt/homebrew/lib/libespeak-ng.1.dylib",
"/usr/local/lib/libespeak-ng.1.dylib",
"/usr/local/lib/libespeak.dylib",
# Linux paths
Expand Down Expand Up @@ -212,6 +211,8 @@ def Synth(
flags=0,
user_data=None,
):
if isinstance(text, str):
text = text.encode("utf-8")
return cSynth(
text,
len(text) * 10,
Expand Down Expand Up @@ -279,7 +280,7 @@ def Synth(
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""


def Synth_Mark(text, index_mark, end_position=0, flags=CHARS_AUTO):
Expand Down Expand Up @@ -309,7 +310,7 @@ def Synth_Mark(text, index_mark, end_position=0, flags=CHARS_AUTO):
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""

Key = cfunc("espeak_Key", dll, c_int, ("key_name", c_char_p, 1))
Key.__doc__ = """Speak the name of a keyboard key.
Expand All @@ -318,15 +319,15 @@ def Synth_Mark(text, index_mark, end_position=0, flags=CHARS_AUTO):
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""

Char = cfunc("espeak_Char", dll, c_int, ("character", c_wchar, 1))
Char.__doc__ = """Speak the name of the given character
Return: EE_OK: operation achieved
EE_BUFFER_FULL: the command can not be buffered;
you may try after a while to call the function again.
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""

# Speech Parameters
SILENCE = 0 # internal use
Expand Down Expand Up @@ -451,11 +452,13 @@ def __repr__(self):


def ListVoices(voice_spec=None):
"""Reads the voice files from espeak-data/voices and returns a list of VOICE objects.
"""
Reads the voice files from espeak-data/voices and returns a list of VOICE objects.
If voice_spec is None then all voices are listed.
If voice spec is given, then only the voices which are compatible with the voice_spec
are listed, and they are listed in preference order."""
are listed, and they are listed in preference order.
"""
ppv = cListVoices(voice_spec)
res = []
i = 0
Expand Down Expand Up @@ -514,12 +517,12 @@ def ListVoices(voice_spec=None):
Synchronize = cfunc("espeak_Synchronize", dll, c_int)
Synchronize.__doc__ = """This function returns when all data have been spoken.
Return: EE_OK: operation achieved
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""

Terminate = cfunc("espeak_Terminate", dll, c_int)
Terminate.__doc__ = """last function to be called.
Return: EE_OK: operation achieved
EE_INTERNAL_ERROR."""
EE_INTERNAL_ERROR."""

Info = cfunc("espeak_Info", dll, c_char_p, ("ptr", c_void_p, 1, 0))
Info.__doc__ = """Returns the version number string.
Expand All @@ -541,7 +544,7 @@ def synth_cb(wav, numsample, events):
SetSynthCallback(synth_cb)
s = "This is a test, only a test. "
uid = c_uint(0)
# print 'pitch=',GetParameter(PITCH)
# print('pitch=',GetParameter(PITCH))
# SetParameter(PITCH, 50, 0)
print(Synth(s))
while IsPlaying():
Expand Down
Loading

0 comments on commit b27c315

Please sign in to comment.