Skip to content

Commit

Permalink
Merge pull request #26 from meemalabs/feature/add-support-for-speech-…
Browse files Browse the repository at this point in the history
…marks

Added support for speech marks.
  • Loading branch information
luigel authored Apr 11, 2021
2 parents e27bb6d + 9011dda commit f9b57ff
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 19 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ $path = TextToSpeech::language('ja-JP')
// use the SSML text type in the convert() method.
$path = TextToSpeech::ssml()
->convert('<speak>Hi There <break /> This is SSML syntax</speak');
// using speech marks.
$output = TextToSpeech::speechMarks(['sentence', 'word', 'viseme', 'ssml'])
->convert('This is a test'); // This will return an array.
```
## Installation
Expand Down Expand Up @@ -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,
Expand All @@ -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.
*/
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
8 changes: 8 additions & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
82 changes: 66 additions & 16 deletions src/Converters/PollyConverter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
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;
use Illuminate\Support\Arr;

class PollyConverter implements Converter
{
use Storable, Sourceable, HasLanguage, SSMLable;
use Storable, Sourceable, HasLanguage, SSMLable, HasSpeechMarks;

/**
* Client instance of Polly.
Expand Down Expand Up @@ -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)
{
Expand All @@ -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(
Expand All @@ -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);
}
Expand Down Expand Up @@ -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.
*
Expand All @@ -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();
}
}
3 changes: 2 additions & 1 deletion src/Facades/TextToSpeech.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
24 changes: 24 additions & 0 deletions src/Traits/HasSpeechMarks.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Cion\TextToSpeech\Traits;

trait HasSpeechMarks
{
/**
* @var array
*/
protected $speechMarks = [];

/**
* Sets the speech mark types.
*
* @param array $speechMarks
* @return $this
*/
public function speechMarks(array $speechMarks)
{
$this->speechMarks = $speechMarks;

return $this;
}
}
10 changes: 10 additions & 0 deletions tests/PollyConverterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

0 comments on commit f9b57ff

Please sign in to comment.