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

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

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",
src/Converters/PollyConverter.phpmodified+52-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,26 @@ class PollyConverter implements Converter
8287 */
8388 protected function synthesizeSpeech($text, array $options = null)
8489 {
90 $arguments = [
91 'LanguageCode' => $this->getLanguage(),
92 'VoiceId' => $this->voice($options),
93 'OutputFormat' => $this->format($options),
94 'TextType' => $this->textType(),
95 'SpeechMarkTypes' => $this->speechMarks,
96 ];
97
8598 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 ]);
99 return $this->client->synthesizeSpeech(array_merge($arguments, [
100 'Text' => $text,
101 ]));
93102 }
94103
95104 $results = [];
96105
97106 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 ]);
107 $result = $this->client->synthesizeSpeech(array_merge($arguments, [
108 'Text' => $textItem,
109 ]));
105110
106111 array_push($results, $result);
107112 }
@@ -190,6 +195,10 @@ class PollyConverter implements Converter
190195 */
191196 protected function format($options)
192197 {
198 if ($this->hasSpeechMarks()) {
199 return 'json';
200 }
201
193202 $default = config('tts.output_format', 'mp3');
194203
195204 return Arr::get($options, 'format', $default);
@@ -205,4 +214,31 @@ class PollyConverter implements Converter
205214 {
206215 return $result->get('AudioStream')->getContents();
207216 }
217
218 /**
219 * Determines if speech marks are set.
220 *
221 * @return bool
222 */
223 protected function hasSpeechMarks()
224 {
225 return ! empty($this->speechMarks);
226 }
227
228 /**
229 * Format the given json string into an array.
230 *
231 * @param string $json
232 * @return array
233 */
234 protected function formatToArray($json)
235 {
236 $jsons = explode(PHP_EOL, $json);
237
238 array_pop($jsons);
239
240 return collect($jsons)->map(function ($json) {
241 return json_decode($json, true);
242 })->toArray();
243 }
208244}
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+26-0
Changes to src/Traits/HasSpeechMarks.php
@@ -0,0 +1,26 @@
1<?php
2
3
4namespace Cion\TextToSpeech\Traits;
5
6
7trait HasSpeechMarks
8{
9 /**
10 * @var array
11 */
12 protected $speechMarks = [];
13
14 /**
15 * Sets the speech mark types.
16 *
17 * @param array $speechMarks
18 * @return $this
19 */
20 public function speechMarks(array $speechMarks)
21 {
22 $this->speechMarks = $speechMarks;
23
24 return $this;
25 }
26}
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}