diff --git a/README.md b/README.md index a3d8cb6..0e2c926 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,10 @@ $path = TextToSpeech::language('ja-JP') // use the SSML text type in the convert() method. $path = TextToSpeech::ssml() ->convert('Hi There This is SSML syntaxconvert('This is a test'); // This will return an array. ``` ## Installation @@ -159,7 +163,7 @@ return [ 'polly' => [ /** * Voice ID to use for the synthesis. - * You may use any of the following: + * You may use any of the following:. * * Aditi, Amy, Astrid, Bianca, Brian, Camila, Carla, Carmen, Celine, * Chantal, Conchita, Cristiano, Dora, Emma, Enrique, Ewa, Filiz, @@ -171,6 +175,14 @@ return [ */ 'voice_id' => env('AWS_VOICE_ID', 'Amy'), + /** + * You can request any or all of the speech mark types, but leave it empty if you don't use speech marks. + * You may add any of the following:. + * + * sentence, word, viseme, ssml + */ + 'speech_marks' => [], + /** * IAM Credentials from AWS. */ diff --git a/composer.json b/composer.json index 0ebc26b..daf6af0 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,8 @@ "php": "^7.3|^7.4|^8.0", "aws/aws-sdk-php": "^3.178", "guzzlehttp/guzzle": "^6.0|^7.0", - "illuminate/support": "5.*|^6.0|^7.0|^8.0" + "illuminate/support": "5.*|^6.0|^7.0|^8.0", + "ext-json": "*" }, "require-dev": { "orchestra/testbench": "^4.0|^5.0|^6.0", diff --git a/config/config.php b/config/config.php index e264a27..12e679d 100644 --- a/config/config.php +++ b/config/config.php @@ -82,6 +82,14 @@ */ 'voice_id' => env('AWS_VOICE_ID', 'Amy'), + /** + * You can request any or all of the speech mark types, but leave it empty if you don't use speech marks. + * You may add any of the following:. + * + * sentence, word, viseme, ssml + */ + 'speech_marks' => [], + /** * IAM Credentials from AWS. */ diff --git a/src/Converters/PollyConverter.php b/src/Converters/PollyConverter.php index 9227d78..8faf49c 100644 --- a/src/Converters/PollyConverter.php +++ b/src/Converters/PollyConverter.php @@ -6,6 +6,7 @@ use Aws\Result; use Cion\TextToSpeech\Contracts\Converter; use Cion\TextToSpeech\Traits\HasLanguage; +use Cion\TextToSpeech\Traits\HasSpeechMarks; use Cion\TextToSpeech\Traits\Sourceable; use Cion\TextToSpeech\Traits\SSMLable; use Cion\TextToSpeech\Traits\Storable; @@ -13,7 +14,7 @@ class PollyConverter implements Converter { - use Storable, Sourceable, HasLanguage, SSMLable; + use Storable, Sourceable, HasLanguage, SSMLable, HasSpeechMarks; /** * Client instance of Polly. @@ -47,7 +48,7 @@ public function getClient(): PollyClient * * @param string $data * @param array $options - * @return string + * @return string|array */ public function convert(string $data, array $options = null) { @@ -59,6 +60,10 @@ public function convert(string $data, array $options = null) $result = $this->synthesizeSpeech($text, $options); + if ($this->hasSpeechMarks()) { + return $this->formatToArray($this->getResultContent($result)); + } + if ($result instanceof Result) { // Store audio file to disk return $this->store( @@ -82,26 +87,28 @@ public function convert(string $data, array $options = null) */ protected function synthesizeSpeech($text, array $options = null) { + $speechMarks = $this->getSpeechMarks(); + + $arguments = [ + 'LanguageCode' => $this->getLanguage(), + 'VoiceId' => $this->voice($options), + 'OutputFormat' => $this->format($options), + 'TextType' => $this->textType(), + 'SpeechMarkTypes' => $speechMarks, + ]; + if (is_string($text)) { - return $this->client->synthesizeSpeech([ - 'LanguageCode' => $this->getLanguage(), - 'VoiceId' => $this->voice($options), - 'OutputFormat' => $this->format($options), - 'TextType' => $this->textType(), - 'Text' => $text, - ]); + return $this->client->synthesizeSpeech(array_merge($arguments, [ + 'Text' => $text, + ])); } $results = []; foreach ($text as $textItem) { - $result = $this->client->synthesizeSpeech([ - 'LanguageCode' => $this->getLanguage(), - 'VoiceId' => $this->voice($options), - 'OutputFormat' => $this->format($options), - 'TextType' => $this->textType(), - 'Text' => $textItem, - ]); + $result = $this->client->synthesizeSpeech(array_merge($arguments, [ + 'Text' => $textItem, + ])); array_push($results, $result); } @@ -190,11 +197,27 @@ protected function getLanguage() */ protected function format($options) { + if ($this->hasSpeechMarks()) { + return 'json'; + } + $default = config('tts.output_format', 'mp3'); return Arr::get($options, 'format', $default); } + /** + * Get the speech marks. + * + * @return array + */ + protected function getSpeechMarks() + { + $default = config('tts.services.polly.speech_marks', []); + + return ! empty($this->speechMarks) ? $this->speechMarks : $default; + } + /** * Get the content of the result from AWS Polly. * @@ -205,4 +228,31 @@ protected function getResultContent($result) { return $result->get('AudioStream')->getContents(); } + + /** + * Determines if speech marks are set. + * + * @return bool + */ + protected function hasSpeechMarks() + { + return ! empty($this->getSpeechMarks()); + } + + /** + * Format the given json string into an array. + * + * @param string $json + * @return array + */ + protected function formatToArray($json) + { + $jsons = explode(PHP_EOL, $json); + + array_pop($jsons); + + return collect($jsons)->map(function ($json) { + return json_decode($json, true); + })->toArray(); + } } diff --git a/src/Facades/TextToSpeech.php b/src/Facades/TextToSpeech.php index f398928..8b22f45 100644 --- a/src/Facades/TextToSpeech.php +++ b/src/Facades/TextToSpeech.php @@ -5,12 +5,13 @@ use Illuminate\Support\Facades\Facade; /** - * @method static void convert($data, array $options) + * @method static string|array convert($data, array $options) * @method static \Cion\TextToSpeech\Contracts\Converter saveTo(string $path) * @method static \Cion\TextToSpeech\Contracts\Converter disk(string $disk) * @method static \Cion\TextToSpeech\Contracts\Converter source(string $source) * @method static \Cion\TextToSpeech\Contracts\Converter language(string $language) * @method static \Cion\TextToSpeech\Contracts\Converter ssml() + * @method static \Cion\TextToSpeech\Contracts\Converter speechMarks(array $speechMarks) */ class TextToSpeech extends Facade { diff --git a/src/Traits/HasSpeechMarks.php b/src/Traits/HasSpeechMarks.php new file mode 100644 index 0000000..af68a1e --- /dev/null +++ b/src/Traits/HasSpeechMarks.php @@ -0,0 +1,24 @@ +speechMarks = $speechMarks; + + return $this; + } +} diff --git a/tests/PollyConverterTest.php b/tests/PollyConverterTest.php index 4279825..72b7eac 100644 --- a/tests/PollyConverterTest.php +++ b/tests/PollyConverterTest.php @@ -97,4 +97,14 @@ public function it_should_specify_path_source_and_be_able_to_retrieve_text() Storage::assertExists($path); } + + /** @test */ + public function it_should_return_an_array_when_speech_marks_are_set() + { + $converter = new PollyConverter($this->client); + + $result = $converter->speechMarks(['sentence'])->convert('test'); + + $this->assertIsArray($result); + } }