ケイン・コスギ(和英混在の文章を PowerShell に喋らせる)

和英混在の文章を 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 # =============================================

なお、「あ~ちゃん」は「アカラチャン」と読んでしまいます。切ない。




新TOEICテスト出る語句1800[CD2枚付]