-
Notifications
You must be signed in to change notification settings - Fork 1
/
powershell-google-tts.psm1
114 lines (97 loc) · 3.94 KB
/
powershell-google-tts.psm1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
$baseUrl = 'https://texttospeech.googleapis.com/v1/';
function Get-GoogleTTSVoices() {
if ($null -eq $env:GOOGLE_API_KEY_TTS) {
throw 'You must set the GOOGLE_API_KEY_TTS environment variable to use GoogleTTS.'
}
return Invoke-WebRequest -Uri ($baseUrl + 'voices?key=' + $env:GOOGLE_API_KEY_TTS) -ContentType 'application/json' -Method GET | ConvertFrom-Json;
}
$completer = {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
$upper = $wordToComplete.ToUpper()
(Get-GoogleTTSVoices).voices.name | Where-Object {
$_.ToUpper() -like "$upper*"
} | ForEach-Object {
$_;
}
}
# requires ffplay (can be installed from ffmpeg)
function Start-GoogleTTS ($text, $speed, $outFile, $voiceName) {
if ($null -eq $env:GOOGLE_API_KEY_TTS) {
throw 'You must set the GOOGLE_API_KEY_TTS environment variable to use GoogleTTS.'
}
$tmpConcatFileName = '.powershell-google-tts-concat.txt';
if (Test-Path $tmpConcatFileName) {
Remove-Item $tmpConcatFileName;
}
$text = $text.Replace('“', "").Replace('”', "");
$text = "$text";
$data = [psobject]::new()
$audioConfig = [psobject]::new();
$audioConfig | Add-Member -NotePropertyName 'audioEncoding' -NotePropertyValue 'MP3';
if ($null -ne $speed) {
$audioConfig | Add-Member -NotePropertyName 'speakingRate' -NotePropertyValue $speed
}
if ($null -eq $voiceName) {
$voiceName = 'en-US-Standard-C';
}
$i = 0;
$j = 0;
$parts = $text.Split(' ');
$outFiles = [System.Collections.Generic.List[string]]::new();
$deleteSpokenFile = $null -eq $outFile;
$inputParam = [psobject]::new();
$inputParam | Add-Member -NotePropertyName 'text' -NotePropertyValue $null;
$voice = [psobject]::new();
$voice | Add-Member -NotePropertyName 'languageCode' -NotePropertyValue 'en-US';
$voice | Add-Member -NotePropertyName 'name' -NotePropertyValue $voiceName;
$data | Add-Member -NotePropertyName 'audioConfig' -NotePropertyValue $audioConfig;
$data | Add-Member -NotePropertyName 'input' -NotePropertyValue $inputParam;
$data | Add-Member -NotePropertyName 'voice' -NotePropertyValue $voice;
# Google limits how large each request can be by text length.
while ($i -lt $text.Length / 5000) {
$chunk = '';
while ($j -lt $parts.Length -and ($chunk.Length + $parts[$j].Length + 1) -lt 5000) {
$chunk += $parts[$j] + ' ';
$j++;
}
$inputParam.text = $chunk;
$response = Invoke-WebRequest -Uri ($baseUrl + 'text:synthesize?key=' + $env:GOOGLE_API_KEY_TTS) -ContentType 'application/json' -Body (ConvertTo-Json $data) -Method POST;
$audioData = $response.Content | ConvertFrom-Json;
$base64 = [System.Convert]::FromBase64String($audioData.audioContent);
$tempPath = $env:TEMP;
if ($null -eq $tempPath) {
$tempPath = "/tmp";
}
$tmpFile = "$tempPath/$([System.DateTime]::Now.ToSTring('yyyy-MM-dd-hh-mm-ss-ff')).mp3";
$writeFile = "$outFile.$i";
if ($deleteSpokenFile) {
$writeFile = $tmpFile;
}
[System.IO.File]::WriteAllBytes($writeFile, $base64);
if ($deleteSpokenFile) {
ffplay -nodisp -autoexit -hide_banner -loglevel panic $writeFile > $null;
Remove-Item $writeFile -Force;
}
else {
# add it to file for concatenation
$outFiles.Add($writeFile);
"file '$writeFile'" | Out-File $tmpConcatFileName -Append -Encoding ascii;
}
$i++;
}
# If the user wants to keep the audio output
if (-not $deleteSpokenFile) {
# concatenate it if it was large
if ($outFiles.Count -gt 1) {
ffmpeg -f concat -safe 0 -i $tmpConcatFileName -c copy $outFile
$outFiles | ForEach-Object {
Remove-Item $_ -Force
}
} else {
# otherwise just rename it from "<out-file>.0" to "<out-file>"
Move-Item $outFiles[0] $outFile
}
Remove-Item $tmpConcatFileName -Force
}
}
Register-ArgumentCompleter -CommandName Start-GoogleTTS -ParameterName voiceName -ScriptBlock $completer;