ReviewOS

also looking at this

meemalabs/laravel-text-to-speech

Added support for speech marks.

#26
Merged luigel wants to merge feature/add-support-for-speech-marks into main
7 files +125 -19
README.mdmodified+13-1
Changes to README.md
@@ -53,6 +53,10 @@ $path = TextToSpeech::language('ja-JP')
5353// use the SSML text type in the convert() method.
5454$path = TextToSpeech::ssml()
5555 ->convert('<speak>Hi There <break /> This is SSML syntax</speak');
56
57// using speech marks.
58$output = TextToSpeech::speechMarks(['sentence', 'word', 'viseme', 'ssml'])
59 ->convert('This is a test'); // This will return an array.
5660```
5761
5862## Installation
@@ -159,7 +163,7 @@ return [
159163 'polly' => [
160164 /**
161165 * Voice ID to use for the synthesis.
162 * You may use any of the following:
166 * You may use any of the following:.
163167 *
164168 * Aditi, Amy, Astrid, Bianca, Brian, Camila, Carla, Carmen, Celine,
165169 * Chantal, Conchita, Cristiano, Dora, Emma, Enrique, Ewa, Filiz,
@@ -171,6 +175,14 @@ return [
171175 */
172176 'voice_id' => env('AWS_VOICE_ID', 'Amy'),
173177
178 /**
179 * You can request any or all of the speech mark types, but leave it empty if you don't use speech marks.
180 * You may add any of the following:.
181 *
182 * sentence, word, viseme, ssml
183 */
184 'speech_marks' => [],
185
174186 /**
175187 * IAM Credentials from AWS.
176188 */
composer.jsonmodified+2-1
Changes to composer.json
@@ -28,7 +28,8 @@
2828 "php": "^7.3|^7.4|^8.0",
2929 "aws/aws-sdk-php": "^3.178",
3030 "guzzlehttp/guzzle": "^6.0|^7.0",
31 "illuminate/support": "5.*|^6.0|^7.0|^8.0"
31 "illuminate/support": "5.*|^6.0|^7.0|^8.0",
32 "ext-json": "*"
3233 },
3334 "require-dev": {
3435 "orchestra/testbench": "^4.0|^5.0|^6.0",
config/config.phpmodified+8-0
Changes to config/config.php
@@ -82,6 +82,14 @@ return [
8282 */
8383 'voice_id' => env('AWS_VOICE_ID', 'Amy'),
8484
85 /**
86 * You can request any or all of the speech mark types, but leave it empty if you don't use speech marks.
87 * You may add any of the following:.
88 *
89 * sentence, word, viseme, ssml
90 */
91 'speech_marks' => [],
92
8593 /**
8694 * IAM Credentials from AWS.
8795 */
src/Converters/PollyConverter.phpmodified+66-16
Changes to src/Converters/PollyConverter.php
@@ -6,6 +6,7 @@ use Aws\Polly\PollyClient;
66use Aws\Result;
77use Cion\TextToSpeech\Contracts\Converter;
88use Cion\TextToSpeech\Traits\HasLanguage;
9use Cion\TextToSpeech\Traits\HasSpeechMarks;
910use Cion\TextToSpeech\Traits\Sourceable;
1011use Cion\TextToSpeech\Traits\SSMLable;
1112use Cion\TextToSpeech\Traits\Storable;
@@ -13,7 +14,7 @@ use Illuminate\Support\Arr;
1314
1415class PollyConverter implements Converter
1516{
16 use Storable, Sourceable, HasLanguage, SSMLable;
17 use Storable, Sourceable, HasLanguage, SSMLable, HasSpeechMarks;
1718
1819 /**
1920 * Client instance of Polly.
@@ -47,7 +48,7 @@ class PollyConverter implements Converter
4748 *
4849 * @param string $data
4950 * @param array $options
50 * @return string
51 * @return string|array
5152 */
5253 public function convert(string $data, array $options = null)
5354 {
@@ -59,6 +60,10 @@ class PollyConverter implements Converter
5960
6061 $result = $this->synthesizeSpeech($text, $options);
6162
63 if ($this->hasSpeechMarks()) {
64 return $this->formatToArray($this->getResultContent($result));
65 }
66
6267 if ($result instanceof Result) {
6368 // Store audio file to disk
6469 return $this->store(
@@ -82,26 +87,28 @@ class PollyConverter implements Converter
8287 */
8388 protected function synthesizeSpeech($text, array $options = null)
8489 {
90 $speechMarks = $this->getSpeechMarks();
91
92 $arguments = [
93 'LanguageCode' => $this->getLanguage(),
94 'VoiceId' => $this->voice($options),
95 'OutputFormat' => $this->format($options),
96 'TextType' => $this->textType(),
97 'SpeechMarkTypes' => $speechMarks,
98 ];
99
85100 if (is_string($text)) {
86 return $this->client->synthesizeSpeech([
87 'LanguageCode' => $this->getLanguage(),
88 'VoiceId' => $this->voice($options),
89 'OutputFormat' => $this->format($options),
90 'TextType' => $this->textType(),
91 'Text' => $text,
92 ]);
101 return $this->client->synthesizeSpeech(array_merge($arguments, [
102 'Text' => $text,
103 ]));
93104 }
94105
95106 $results = [];
96107
97108 foreach ($text as $textItem) {
98 $result = $this->client->synthesizeSpeech([
99 'LanguageCode' => $this->getLanguage(),
100 'VoiceId' => $this->voice($options),
101 'OutputFormat' => $this->format($options),
102 'TextType' => $this->textType(),
103 'Text' => $textItem,
104 ]);
109 $result = $this->client->synthesizeSpeech(array_merge($arguments, [
110 'Text' => $textItem,
111 ]));
105112
106113 array_push($results, $result);
107114 }
@@ -190,11 +197,27 @@ class PollyConverter implements Converter
190197 */
191198 protected function format($options)
192199 {
200 if ($this->hasSpeechMarks()) {
201 return 'json';
202 }
203
193204 $default = config('tts.output_format', 'mp3');
194205
195206 return Arr::get($options, 'format', $default);
196207 }
197208
209 /**
210 * Get the speech marks.
211 *
212 * @return array
213 */
214 protected function getSpeechMarks()
215 {
216 $default = config('tts.services.polly.speech_marks', []);
217
218 return ! empty($this->speechMarks) ? $this->speechMarks : $default;
219 }
220
198221 /**
199222 * Get the content of the result from AWS Polly.
200223 *
@@ -205,4 +228,31 @@ class PollyConverter implements Converter
205228 {
206229 return $result->get('AudioStream')->getContents();
207230 }
231
232 /**
233 * Determines if speech marks are set.
234 *
235 * @return bool
236 */
237 protected function hasSpeechMarks()
238 {
239 return ! empty($this->getSpeechMarks());
240 }
241
242 /**
243 * Format the given json string into an array.
244 *
245 * @param string $json
246 * @return array
247 */
248 protected function formatToArray($json)
249 {
250 $jsons = explode(PHP_EOL, $json);
251
252 array_pop($jsons);
253
254 return collect($jsons)->map(function ($json) {
255 return json_decode($json, true);
256 })->toArray();
257 }
208258}
src/Facades/TextToSpeech.phpmodified+2-1
Changes to src/Facades/TextToSpeech.php
@@ -5,12 +5,13 @@ namespace Cion\TextToSpeech\Facades;
55use Illuminate\Support\Facades\Facade;
66
77/**
8 * @method static void convert($data, array $options)
8 * @method static string|array convert($data, array $options)
99 * @method static \Cion\TextToSpeech\Contracts\Converter saveTo(string $path)
1010 * @method static \Cion\TextToSpeech\Contracts\Converter disk(string $disk)
1111 * @method static \Cion\TextToSpeech\Contracts\Converter source(string $source)
1212 * @method static \Cion\TextToSpeech\Contracts\Converter language(string $language)
1313 * @method static \Cion\TextToSpeech\Contracts\Converter ssml()
14 * @method static \Cion\TextToSpeech\Contracts\Converter speechMarks(array $speechMarks)
1415 */
1516class TextToSpeech extends Facade
1617{
src/Traits/HasSpeechMarks.phpadded+24-0
Changes to src/Traits/HasSpeechMarks.php
@@ -0,0 +1,24 @@
1<?php
2
3namespace Cion\TextToSpeech\Traits;
4
5trait HasSpeechMarks
6{
7 /**
8 * @var array
9 */
10 protected $speechMarks = [];
11
12 /**
13 * Sets the speech mark types.
14 *
15 * @param array $speechMarks
16 * @return $this
17 */
18 public function speechMarks(array $speechMarks)
19 {
20 $this->speechMarks = $speechMarks;
21
22 return $this;
23 }
24}
tests/PollyConverterTest.phpmodified+10-0
Changes to tests/PollyConverterTest.php
@@ -97,4 +97,14 @@ class PollyConverterTest extends TextToSpeechTestCase
9797
9898 Storage::assertExists($path);
9999 }
100
101 /** @test */
102 public function it_should_return_an_array_when_speech_marks_are_set()
103 {
104 $converter = new PollyConverter($this->client);
105
106 $result = $converter->speechMarks(['sentence'])->convert('test');
107
108 $this->assertIsArray($result);
109 }
100110}