Passed
Push — master ( 976a6a...998e2e )
by Rigel Kent
13:49
created

PollyConverter   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 180
Duplicated Lines 0 %

Importance

Changes 4
Bugs 3 Features 0
Metric Value
eloc 44
c 4
b 3
f 0
dl 0
loc 180
rs 10
wmc 16

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getLanguage() 0 3 1
A synthesizeSpeech() 0 26 3
A mergeOutputs() 0 8 2
A getResultContent() 0 3 1
A getChunkText() 0 3 1
A format() 0 5 1
A convert() 0 21 3
A __construct() 0 3 1
A isTextAboveLimit() 0 3 1
A getClient() 0 3 1
A voice() 0 5 1
1
<?php
2
3
namespace Cion\TextToSpeech\Converters;
4
5
use Aws\Polly\PollyClient;
6
use Aws\Result;
7
use Cion\TextToSpeech\Contracts\Converter;
8
use Cion\TextToSpeech\Traits\HasLanguage;
9
use Cion\TextToSpeech\Traits\Sourceable;
10
use Cion\TextToSpeech\Traits\Storable;
11
use Illuminate\Support\Arr;
12
13
class PollyConverter implements Converter
14
{
15
    use Storable, Sourceable, HasLanguage;
16
17
    /**
18
     * Client instance of Polly.
19
     *
20
     * @var \Aws\Polly\PollyClient
21
     */
22
    protected $client;
23
24
    /**
25
     * Construct converter.
26
     *
27
     * @param PollyClient $client
28
     */
29
    public function __construct(PollyClient $client)
30
    {
31
        $this->client = $client;
32
    }
33
34
    /**
35
     * Get the Polly Client.
36
     *
37
     * @return \Aws\Polly\PollyClient
38
     */
39
    public function getClient(): PollyClient
40
    {
41
        return $this->client;
42
    }
43
44
    /**
45
     * Converts the text to speech.
46
     *
47
     * @param string $data
48
     * @param array $options
49
     * @return string
50
     */
51
    public function convert(string $data, array $options = null)
52
    {
53
        $text = $this->getTextFromSource($data);
54
55
        if ($this->isTextAboveLimit($text)) {
56
            $text = $this->getChunkText($text);
57
        }
58
59
        $result = $this->synthesizeSpeech($text, $options);
60
61
        if ($result instanceof Result) {
62
            // Store audio file to disk
63
            return $this->store(
64
                $this->getTextFromSource($data),
65
                $this->getResultContent($result)
66
            );
67
        }
68
69
        return $this->store(
70
            $this->getTextFromSource($data),
71
            $this->mergeOutputs($result)
72
        );
73
    }
74
75
    /**
76
     * Request to Amazon Polly to synthesize speech.
77
     *
78
     * @param string|array $text
79
     * @param array $options
80
     * @return array|\Aws\Result
81
     */
82
    protected function synthesizeSpeech($text, array $options = null)
83
    {
84
        if (is_string($text)) {
85
            return $this->client->synthesizeSpeech([
86
                'LanguageCode' => $this->getLanguage(),
87
                'VoiceId'      => $this->voice($options),
88
                'OutputFormat' => $this->format($options),
89
                'TextType'     => 'ssml',
90
                'Text'         => '<speak>'.$text.'</speak>',
91
            ]);
92
        }
93
94
        $results = [];
95
96
        foreach ($text as $item) {
97
            $result = $this->client->synthesizeSpeech([
98
                'LanguageCode' => $this->getLanguage(),
99
                'VoiceId'      => $this->voice($options),
100
                'OutputFormat' => $this->format($options),
101
                'Text'         => $item,
102
            ]);
103
104
            array_push($results, $result);
105
        }
106
107
        return $results;
108
    }
109
110
    /**
111
     * Merges the output from amazon polly.
112
     *
113
     * @return mixed
114
     */
115
    protected function mergeOutputs(array $results)
116
    {
117
        $mergedResult = null;
118
        foreach ($results as $result) {
119
            $mergedResult .= $this->getResultContent($result);
120
        }
121
122
        return $mergedResult;
123
    }
124
125
    /**
126
     * Checks the length of the text if more than 3000.
127
     *
128
     * @param string $text
129
     * @return bool
130
     */
131
    protected function isTextAboveLimit(string $text)
132
    {
133
        return strlen($text) > 2000;
134
    }
135
136
    /**
137
     * Chunk the given text into array.
138
     *
139
     * @param string $text
140
     * @param int $size
141
     * @return array
142
     */
143
    protected function getChunkText(string $text, int $size = 2000)
144
    {
145
        return explode("\n", wordwrap($text, $size));
146
    }
147
148
    /**
149
     * Get the text to speech voice ID.
150
     *
151
     * @param  array $options
152
     * @return string
153
     */
154
    protected function voice($options)
155
    {
156
        $default = config('tts.services.polly.voice_id', 'Amy');
157
158
        return Arr::get($options, 'voice', $default);
159
    }
160
161
    /**
162
     * Get the language
163
     *
164
     * @return string
165
     */
166
    protected function getLanguage()
167
    {
168
        return $this->language ?? config('tts.language', 'en-US');
169
    }
170
171
    /**
172
     * Get the audio format.
173
     *
174
     * @param  array $options
175
     * @return string
176
     */
177
    protected function format($options)
178
    {
179
        $default = config('tts.output_format', 'mp3');
180
181
        return Arr::get($options, 'format', $default);
182
    }
183
184
    /**
185
     * Get the content of the result from AWS Polly.
186
     *
187
     * @param mixed $result
188
     * @return mixed
189
     */
190
    protected function getResultContent($result)
191
    {
192
        return $result->get('AudioStream')->getContents();
193
    }
194
}
195