Skip to content

Commit

Permalink
2 tts command (#4)
Browse files Browse the repository at this point in the history
* checkpoint

* update

* monitor queue

* v0.3.0

---------

Co-authored-by: yuta0306 <yuuta.20010306@gmail.com>
  • Loading branch information
yuta0306 and yuta0306 committed Oct 2, 2023
1 parent 67aaaa6 commit c7f8f58
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 4 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,5 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

.vscode/
.vscode/
tests/
2 changes: 1 addition & 1 deletion dslclib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
OutputForSTTRecognition,
)

__version__ = "0.2.0"
__version__ = "0.3.0"
82 changes: 80 additions & 2 deletions dslclib/src/tts.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import json
from typing import Optional
import time
import threading
import warnings

from dslclib.src.base import BaseClient

Expand Down Expand Up @@ -51,13 +54,35 @@ def __new__(
return super().__new__(cls, json.dumps(data, ensure_ascii=False))


class QueueSupervisor(threading.Thread):
def __init__(self, client, **kwargs) -> None:
super().__init__(**kwargs)
self.client = client
self.should_stop = threading.Event()

def run(self):
while not self.should_stop.wait(0):
try:
self.client.monitor_queue()
except ConnectionAbortedError:
break
print("QueueSupervisorはシャットダウンされました。")

def kill(self):
self.should_stop.set()


class Text2SpeechClient(BaseClient):
"""Text2SpeechClient
音声にしたい発話テキストをソケットに送信するクライアント
"""

def __init__(self, ip: Optional[str] = None, port: int = 3456) -> None:
def __init__(
self,
ip: Optional[str] = None,
port: int = 3456,
) -> None:
"""
Parameters
----------
Expand Down Expand Up @@ -86,6 +111,43 @@ def __init__(self, ip: Optional[str] = None, port: int = 3456) -> None:
>>>
"""
super().__init__(ip, port)
self.queue = list()
self.supervisor = QueueSupervisor(self, daemon=False)
self.supervisor.start()

def close(self) -> None:
self.supervisor.should_stop.set()
return super().close()

def monitor_queue(self):
"""
キューを監視し、合成音声の再生を終えたのちにキューからコマンドを削除するメソッド
**注意**: このメソッドは`self.supervisor`から呼び出されることを推奨する
"""
received = json.loads(str(self.sock.recv(4096).decode()))
if "result" in list(received.keys()) and received["result"] == "success-end":
self.queue.pop(0)

def is_speaking(self) -> bool:
"""
音声を再生中かどうかを確認するメソッド
"""
self.sock.send(json.dumps({"engine": "ISSPEAKING"}).encode())
received = json.loads(str(self.sock.recv(1024).decode()))
if "isSpeaking" in list(received.keys()):
return received["isSpeaking"] == True
return False

def stop_speaking(self) -> None:
self.sock.send(json.dumps({"engine": "STOP"}).encode())

def wait_finish_speaking(self, timeout: float = -1.0) -> None:
if timeout > 0:
raise NotImplementedError
while True:
received = json.loads(str(self.sock.recv(4096).decode()))
if "result" in list(received.keys()) and received["result"] == "success-end":
break

def speech(
self,
Expand All @@ -98,6 +160,8 @@ def speech(
vocal_tract_length: int = 0,
duration_information: bool = False,
speechmark: bool = False,
max_num_queue: int = 1,
wait_queue: bool = False,
) -> None:
"""
音声にしたい発話テキストと発話音声の設定を入力としてソケットに送信する関数
Expand All @@ -120,11 +184,24 @@ def speech(
duration_information: bool, default = False
speechmark: bool, default = False
スピーチマークが含まれるかどうか
max_num_queue: int, default = 1
TTSコマンドのキューを最大いくつまでプールできるか
wait_queue: bool, default = False
max_num_queueのキュー数を超えた場合、キューが空くまで処理を待つかどうか。
`wait=False`に設定した場合、TTSのコマンドをキューにスタックせずに終了する。
Returns
-------
"""
if len(self.queue) >= max_num_queue:
if wait_queue:
warnings.warn("TTSコマンドの最大キュー数を超えたため、キューが空くまで待機します。")
while len(self.queue) >= max_num_queue:
time.sleep(0.05)
else:
warnings.warn(f"TTSコマンドの最大キュー数を超えたため、`{text}`は音声合成されません。", UserWarning)
return

speech = SpeechConfig(
text=text,
engine=engine,
Expand All @@ -138,6 +215,7 @@ def speech(
)
command = speech + "\n"
self.sock.send(command.encode())
self.queue.append(command)


if __name__ == "__main__":
Expand Down

0 comments on commit c7f8f58

Please sign in to comment.