和英混在の文章を PowerShell に喋らせる
ヤスタカの続き。
ハルカさんだけじゃなく
貧乏性と収集癖を駆使して:
165.4MB。んなことしてなんになる。
SRとTTSの違いはなんだろう? ハルカさんは TTS だったので、TTS だけでいいのかも。なお、わかると思いますが一応:
1. en-US -> American English (US: United States)
2. en-AU -> Australian English
3. en-CA -> Canadian English
4. en-GB -> British English (GB: Great Britain)
5. en-IN -> Indian English
ハルカさんだけじゃなくなったので
音声の選択をするわけね。その前に、プログラムから列挙してみねばならん:
1 PS C:\Users\hhsprings> [Reflection.Assembly]::LoadWithPartialName("Microsoft.Speech")
2
3 GAC Version Location
4 --- ------- --------
5 True v2.0.50727 C:\Windows\assembly\GAC_MSIL\Microsoft.Speech\11.0.0.0__31bf3856ad364e35\Microsoft.Speech.dll
6
7
8 PS C:\Users\hhsprings> $speak = New-Object Microsoft.Speech.Synthesis.SpeechSynthesizer
9 PS C:\Users\hhsprings> foreach ($vi in $speak.GetInstalledVoices()) { [Console]::WriteLine($vi.VoiceInfo.Name) }
10 Microsoft Server Speech Text to Speech Voice (en-AU, Hayley)
11 Microsoft Server Speech Text to Speech Voice (en-CA, Heather)
12 Microsoft Server Speech Text to Speech Voice (en-GB, Hazel)
13 Microsoft Server Speech Text to Speech Voice (en-IN, Heera)
14 Microsoft Server Speech Text to Speech Voice (en-US, Helen)
15 Microsoft Server Speech Text to Speech Voice (en-US, ZiraPro)
16 Microsoft Server Speech Text to Speech Voice (ja-JP, Haruka)
17 PS C:\Users\hhsprings>
音声の切り替えは SelectVoice:
1 PS C:\Users\hhsprings> $speak.SelectVoice('Microsoft Server Speech Text to Speech Voice (en-US, ZiraPro)')
2 PS C:\Users\hhsprings> $speak.Voice
3
4
5 Gender : Female
6 Age : Adult
7 Name : Microsoft Server Speech Text to Speech Voice (en-US, ZiraPro)
8 Culture : en-US
9 Id : TTS_MS_en-US_ZiraPro_11.0
10 Description : Microsoft Server Speech Text to Speech Voice (en-US, ZiraPro)
11 SupportedAudioFormats : {Microsoft.Speech.AudioFormat.SpeechAudioFormatInfo}
12 AdditionalInfo : {[, ], [Age, Adult], [AudioFormats, 18], [Gender, Female]...}
13
14
15
16 PS C:\Users\hhsprings>
なお、このまま対話的に「確認」したいなら、
1 $speak.SetOutputToDefaultAudioDevice()
として、スピーカーに向けておく。の上で
1 $speak.Speak("Hello")
で、ZiraProお嬢が喋ってくれる。
英語部分と日本語部分の分離
PowerShell はまだ不慣れなので、これは Python でやってしまう。こんな感じかな:
1 # -*- coding: utf-8 -*-
2 #import sys
3 #import codecs
4 import unicodedata
5 #sys.stdout = codecs.getwriter('utf-8')(sys.stdout)
6
7 def _split(s):
8 wc = False
9 st = 0
10 for i, c in enumerate(s):
11 wc_c = unicodedata.east_asian_width(c) in ('W', 'F')
12 if wc != wc_c:
13 r = s[st:i].strip()
14 if r:
15 yield r, wc
16 wc = wc_c
17 st = i
18 r = s[st:].strip()
19 if r:
20 yield r, wc
21
22
23 #s = open(sys.argv[1], "rb").read().decode("utf-8").strip()
24 #for sp in _split(s):
25 # print(sp[0], sp[1])
なんか「もっさり」しててダサくもみえるが、まぁよかろう。(もっさりというか、C/C++ならともかく、スクリプト言語で一文字ずつ処理って、オーバヘッド高いしさ。)
全体あわせて
です:
Acronym を PowerShell に喋らせる、(裏)Acronym を PowerShell に喋らせるからの流れで、Python 側に多くの処理がいるのは一緒。で、吐き出す ps1 はこうしたいのです:
1 [Reflection.Assembly]::LoadWithPartialName("Microsoft.Speech")
2 $speak = New-Object Microsoft.Speech.Synthesis.SpeechSynthesizer
3 $speak.Rate = 3 # from -10 to 10, default is zero.
4 $speak.SetOutputToWaveFile("C:\Users\hhsprings\mmm.txt.mp3")
5 $speak.SelectVoice("Microsoft Server Speech Text to Speech Voice (ja-JP, Haruka)")
6 $speak.Speak("かしゆかです。のっちです。あぁちゃんです。三人合わせて")
7 $speak.SelectVoice("Microsoft Server Speech Text to Speech Voice (en-US, Helen)")
8 $speak.Speak("Perfume")
9 $speak.SelectVoice("Microsoft Server Speech Text to Speech Voice (ja-JP, Haruka)")
10 $speak.Speak("です。よろしくお願いします。")
11 $speak.Dispose()
ので、スクリプト全体通して:
1 # -*- coding: utf-8 -*-
2 from os import path
3 import sys
4 import codecs
5 import subprocess
6
7
8 #
9 def _split(s):
10 import unicodedata
11
12 wc = False
13 st = 0
14 for i, c in enumerate(s):
15 wc_c = unicodedata.east_asian_width(c) in ('W', 'F')
16 if wc != wc_c:
17 r = s[st:i].strip()
18 if r:
19 yield r, wc
20 wc = wc_c
21 st = i
22 r = s[st:].strip()
23 if r:
24 yield r, wc
25
26
27 # =============================================
28 ifn = sys.argv[1]
29 fn = "tmp.ps1"
30 fo = codecs.getwriter('cp932')(open(fn, "w"))
31
32 # ---------------------------------------------
33 fo.write("""\
34 [Reflection.Assembly]::LoadWithPartialName("Microsoft.Speech")
35 $speak = New-Object Microsoft.Speech.Synthesis.SpeechSynthesizer
36 $speak.Rate = 3 # from -10 to 10, default is zero.
37 $speak.SetOutputToWaveFile("{}.mp3")
38 """.format(path.join(path.abspath("."), path.basename(ifn))))
39 # ---------------------------------------------
40
41 #
42 _voice = {
43 True: "Microsoft Server Speech Text to Speech Voice (ja-JP, Haruka)",
44 False: "Microsoft Server Speech Text to Speech Voice (en-US, Helen)",
45 }
46
47 # ---------------------------------------------
48 s = open(ifn, "rb").read().decode("cp932").strip()
49 for sp in _split(s):
50 fo.write(u"""\
51 $speak.SelectVoice("{}")
52 $speak.Speak("{}")
53 """.format(_voice[sp[1]], sp[0]))
54 # ---------------------------------------------
55 fo.write("""$speak.Dispose()
56 """)
57 fo.close()
58 # ---------------------------------------------
59
60 # =============================================
61 subprocess.call([
62 "C:/WINDOWS/SysWOW64/WindowsPowerShell/v1.0/powershell",
63 path.abspath(fn)])
64 # =============================================
なお、「あ~ちゃん」は「アカラチャン」と読んでしまいます。切ない。
![]() |