Lower default rank for non-RT voices and restrict to Windows 10 October 2018 or greater

This commit is contained in:
Ryan Aird 2020-12-19 20:10:23 -06:00
parent 56703e5f3a
commit 9a0b112a0f
2 changed files with 22 additions and 5 deletions

View file

@ -5,6 +5,7 @@ from __future__ import annotations
import atexit import atexit
import os import os
import platform
import re import re
import subprocess import subprocess
import sys import sys
@ -916,10 +917,14 @@ def setup_audio(taskman: TaskManager, base_folder: str) -> None:
av_player.players.append(MacTTSPlayer(taskman)) av_player.players.append(MacTTSPlayer(taskman))
elif isWin: elif isWin:
from aqt.tts import WindowsTTSPlayer, WindowsRTTTSFilePlayer from aqt.tts import WindowsRTTTSFilePlayer, WindowsTTSPlayer
av_player.players.append(WindowsTTSPlayer(taskman)) av_player.players.append(WindowsTTSPlayer(taskman))
av_player.players.append(WindowsRTTTSFilePlayer(taskman))
if platform.release() == "10":
# If Windows 10, ensure it's October 2018 update or later
if int(platform.version().split(".")[-1]) >= 17763:
av_player.players.append(WindowsRTTTSFilePlayer(taskman))
# cleanup at shutdown # cleanup at shutdown
atexit.register(av_player.shutdown) atexit.register(av_player.shutdown)

View file

@ -25,11 +25,11 @@ expose the name of the engine, which would mean the user could write
from __future__ import annotations from __future__ import annotations
import asyncio
import os import os
import re import re
import subprocess import subprocess
import threading import threading
import asyncio
from concurrent.futures import Future from concurrent.futures import Future
from dataclasses import dataclass from dataclasses import dataclass
from operator import attrgetter from operator import attrgetter
@ -470,6 +470,7 @@ if isWin:
return LCIDS.get(dec_str, "unknown") return LCIDS.get(dec_str, "unknown")
class WindowsTTSPlayer(TTSProcessPlayer): class WindowsTTSPlayer(TTSProcessPlayer):
default_rank = -1
try: try:
speaker = win32com.client.Dispatch("SAPI.SpVoice") speaker = win32com.client.Dispatch("SAPI.SpVoice")
except: except:
@ -529,14 +530,22 @@ if isWin:
def import_voices(self) -> None: def import_voices(self) -> None:
import winrt.windows.media.speechsynthesis as speechsynthesis import winrt.windows.media.speechsynthesis as speechsynthesis
self.voice_list = speechsynthesis.SpeechSynthesizer.get_all_voices() self.voice_list = speechsynthesis.SpeechSynthesizer.get_all_voices()
def get_available_voices(self) -> List[TTSVoice]: def get_available_voices(self) -> List[TTSVoice]:
t = threading.Thread(target=self.import_voices) t = threading.Thread(target=self.import_voices)
t.start() t.start()
t.join() t.join()
return list(map(self._voice_to_object, self.voice_list)) return list(map(self._voice_to_object, self.voice_list))
def _voice_to_object(self, voice: Any) -> TTSVoice: def _voice_to_object(self, voice: Any) -> TTSVoice:
return WindowsRTVoice(id=voice.id, name=voice.display_name.replace(" ", "_"), lang=voice.language.replace("-", "_")) return WindowsRTVoice(
id=voice.id,
name=voice.display_name.replace(" ", "_"),
lang=voice.language.replace("-", "_"),
)
def _play(self, tag: AVTag) -> None: def _play(self, tag: AVTag) -> None:
assert isinstance(tag, TTSTag) assert isinstance(tag, TTSTag)
match = self.voice_for_tag(tag) match = self.voice_for_tag(tag)
@ -547,6 +556,7 @@ if isWin:
lambda: gui_hooks.av_player_did_begin_playing(self, tag) lambda: gui_hooks.av_player_did_begin_playing(self, tag)
) )
asyncio.run(self.speakText(tag, voice.id)) asyncio.run(self.speakText(tag, voice.id))
def _on_done(self, ret: Future, cb: OnDoneCallback): def _on_done(self, ret: Future, cb: OnDoneCallback):
ret.result() ret.result()
@ -557,9 +567,11 @@ if isWin:
# then tell player to advance, which will cause the file to be played # then tell player to advance, which will cause the file to be played
cb() cb()
async def speakText(self, tag: TTSTag, voice_id): async def speakText(self, tag: TTSTag, voice_id):
import winrt.windows.media.speechsynthesis as speechsynthesis import winrt.windows.media.speechsynthesis as speechsynthesis
import winrt.windows.storage.streams as streams import winrt.windows.storage.streams as streams
synthesizer = speechsynthesis.SpeechSynthesizer() synthesizer = speechsynthesis.SpeechSynthesizer()
voices = speechsynthesis.SpeechSynthesizer.get_all_voices() voices = speechsynthesis.SpeechSynthesizer.get_all_voices()
@ -574,7 +586,7 @@ if isWin:
inputStream = stream.get_input_stream_at(0) inputStream = stream.get_input_stream_at(0)
dataReader = streams.DataReader(inputStream) dataReader = streams.DataReader(inputStream)
dataReader.load_async(stream.size) dataReader.load_async(stream.size)
f = open(self.tmppath, 'wb') f = open(self.tmppath, "wb")
for x in range(stream.size): for x in range(stream.size):
f.write(bytes([dataReader.read_byte()])) f.write(bytes([dataReader.read_byte()]))
f.close() f.close()