Windows機でテキストを読み上げさせる(2回目)

win32comを使ってWindows機でテキストを読み上げさせる試みを行った。
Windows Runtime APIsを使って読み上げさせることもできる。

Pythonからこれらを使用するためにwinrtをインストールする。
pip install winrt

インターネットでコードの例を探す。
しかし、C#で記述された例は多いが、Pythonを使う例は乏しい…
print(MediaPlayer.__dict__)などでメソッドや属性を表示して確認するw
Microsoftの説明でのメソッド名やプロパティ名はキャメルケースだが、Pythonのwinrtでのそれらはスネークケースだ。
イベントに関数を追加する方法はPythonとC#とで異なる。
例えばイベントMediaPlayer.MediaEndedならばadd_media_endedを使う。

すばらしいサイトWinRTで音声合成を参考にして、こんな感じで読み上げさせられる。
import time
import asyncio
from winrt.windows.media.core import MediaSource
from winrt.windows.media.playback import MediaPlayer
from winrt.windows.media.speechsynthesis import SpeechSynthesizer

# 確認用
# for voice in SpeechSynthesizer.get_all_voices(): print('{} / {} / {} / {} / {}'.format(voice.id, voice.display_name, voice.language, voice.description, voice.gender))
# print(SpeechSynthesizer.get_default_voice())

async def synthesize_text(text, voice=None):
	synth = SpeechSynthesizer()
	if voice is not None: synth.voice = voice
	return await synth.synthesize_text_to_stream_async(text)

async def play(stream):
	class Control():
		is_waiting = True
		async def wait(self):
			while self.is_waiting: time.sleep(.5)
		def close(self, *args):
			self.is_waiting = False
	control = Control()
	player = MediaPlayer()
	player.source = MediaSource.create_from_stream(stream, stream.content_type)
	player.add_media_ended(control.close)
	player.play()
	await control.wait()
	
stream = asyncio.run(synthesize_text('13番線に停車中の列車は、17時30分発、寝台特急、北斗星1号、札幌行きです'))
print(stream, stream.size, stream.content_type)
asyncio.run(play(stream))
print('done')
再生の終了まで待つためにクラスControlを設けたが、スマートにしたい…
2022/01/08 11:44
タグ