Skip to content

Commit 1b4a0e4

Browse files
add speaker support for gtts-cli | mpv (wustho#88)
1 parent c7c0de3 commit 1b4a0e4

File tree

4 files changed

+44
-2
lines changed

4 files changed

+44
-2
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ List of supported engines:
140140

141141
- `mimic`
142142
- `pico2wave`
143+
- `gtts-mpv` (requires both [gTTS](https://pypi.org/project/gTTS) and [MPV](https://www.mpv.io))
143144

144145
## Dictionary
145146

src/epy_reader/speakers/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
"SpeakerBaseModel",
33
"SpeakerMimic",
44
"SpeakerPico",
5+
"SpeakerGttsMPV"
56
]
67

78
from epy_reader.speakers.base import SpeakerBaseModel
89
from epy_reader.speakers.mimic import SpeakerMimic
910
from epy_reader.speakers.pico import SpeakerPico
11+
from epy_reader.speakers.gtts_mpv import SpeakerGttsMPV

src/epy_reader/speakers/gtts_mpv.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python3
2+
3+
4+
import shutil
5+
import subprocess
6+
7+
from epy_reader.speakers.base import SpeakerBaseModel
8+
9+
10+
class SpeakerGttsMPV(SpeakerBaseModel):
11+
cmd = "gtts-mpv"
12+
available = bool(shutil.which("gtts-cli") and shutil.which("mpv"))
13+
14+
def speak(self, text: str) -> None:
15+
self._gtts_process = subprocess.Popen(
16+
["gtts-cli", "-", *self.args],
17+
text=True,
18+
stdin=subprocess.PIPE,
19+
stdout=subprocess.PIPE,
20+
)
21+
self._mpv_process = subprocess.Popen(
22+
["mpv", "-"],
23+
stdin=self._gtts_process.stdout,
24+
stdout=subprocess.DEVNULL,
25+
stderr=subprocess.DEVNULL,
26+
)
27+
assert self._gtts_process.stdin
28+
self._gtts_process.stdin.write(text)
29+
self._gtts_process.stdin.close()
30+
31+
def is_done(self) -> bool:
32+
return self._mpv_process.poll() is not None
33+
34+
def stop(self) -> None:
35+
self._gtts_process.terminate()
36+
self._mpv_process.terminate()
37+
38+
def cleanup(self) -> None:
39+
pass

src/epy_reader/utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from epy_reader.lib import is_url, tuple_subtract
1111
from epy_reader.models import Key, LettersCount, NoUpdate, ReadingState, TextStructure, TocEntry
1212
from epy_reader.parser import parse_html
13-
from epy_reader.speakers import SpeakerBaseModel, SpeakerMimic, SpeakerPico
13+
from epy_reader.speakers import SpeakerBaseModel, SpeakerMimic, SpeakerPico, SpeakerGttsMPV
1414

1515

1616
def get_ebook_obj(filepath: str) -> Ebook:
@@ -367,7 +367,7 @@ def count_letters_parallel(ebook: Ebook, child_conn) -> None:
367367
def construct_speaker(
368368
preferred: Optional[str] = None, args: List[str] = []
369369
) -> Optional[SpeakerBaseModel]:
370-
available_speakers = [SpeakerMimic, SpeakerPico]
370+
available_speakers = [SpeakerMimic, SpeakerPico, SpeakerGttsMPV]
371371
sorted_speakers = (
372372
sorted(available_speakers, key=lambda x: int(x.cmd == preferred), reverse=True)
373373
if preferred

0 commit comments

Comments
 (0)