]> _ Git - cubist_azuretts.git/commitdiff
#7542
authorVincent Vanwaelscappel <vincent@cubedesigners.com>
Mon, 23 Jun 2025 14:13:55 +0000 (16:13 +0200)
committerVincent Vanwaelscappel <vincent@cubedesigners.com>
Mon, 23 Jun 2025 14:13:55 +0000 (16:13 +0200)
src/Api.php

index 967f027abb0455bf40dca6fd5dee885bd2081e3e..12d37d32be7e2cb5f86173268d65c2655a668d57 100644 (file)
@@ -7,121 +7,134 @@ use GuzzleHttp\Psr7\Request;
 use GuzzleHttp\Psr7\Response;
 use Illuminate\Support\Facades\Cache;
 
-class Api {
-       /**
-        * @var string
-        */
-       protected $key;
-
-       /**
-        * @var string
-        */
-       protected $region;
-
-       /**
-        * @var null|string
-        */
-       protected $token = null;
-
-       /**
-        * @var int
-        */
-       protected $tokenTime = 0;
-
-
-       /**
-        * @var Client
-        */
-       protected $client;
-
-       public function __construct($key, $region = 'francecentral') {
-               $this->key = $key;
-               $this->region = $region;
-               $this->client = new Client();
-       }
-
-       public function textToSpeech($text, $locale, $gender, $voiceName, $saveToFile) {
-               $ssml = "<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'  xml:lang='$locale'><voice xml:lang='$locale' xml:gender='$gender' name='$voiceName'>";
-               $ssml .= htmlspecialchars($text, ENT_XML1 | ENT_SUBSTITUTE | ENT_QUOTES);
-               $ssml .= "</voice></speak>";
-
-               $this->_call('/v1', 'post', [
-                       'X-Microsoft-OutputFormat' => 'audio-48khz-192kbitrate-mono-mp3',
-                       'Content-type' => 'application/ssml+xml'
-               ], $ssml, ['sink' => $saveToFile]);
-       }
-
-       /**
-        * @param $raw
-        * @return array|false
-        */
-       public function listVoices($raw = false) {
-               $cacheKey = 'azure_tts_voices_' . $raw;
-               Cache::forget($cacheKey);
-               return Cache::remember($cacheKey, 86400, function () use ($raw) {
-                       return $this->_listVoices($raw);
-               });
-       }
-
-       /**
-        * @param $raw bool
-        * @return array|false
-        */
-       protected function _listVoices($raw = false) {
-               $resp = $this->_call('/voices/list');
-               if (!$resp) {
-                       return false;
-               }
-               $j = json_decode($resp->getBody()->getContents(), true);
-               if ($raw) {
-                       return $j;
-               }
-               $res = [];
-               foreach ($j as $voice) {
-                       $res[$voice['Locale'] . '/' . $voice['Gender'] . '/' . $voice['ShortName']] = $voice['DisplayName'] . ' / ' . $voice['Gender'] . ' / ' . $voice['LocaleName'];
-               }
-               return $res;
-       }
-
-       /**
-        * @param string $url
-        * @param string $method
-        * @param array $headers
-        * @param string|null $body
-        * @param array $options
-        * @return Response|false
-        */
-       protected function _call($url, $method = 'get', $headers = [], $body = null, $options = []) {
-
-               if (!$this->checkToken()) {
-                       return false;
-               }
-               $baseURL = 'https://' . $this->region . '.tts.speech.microsoft.com/cognitiveservices/';
-               $headers = array_merge([
-                       'Authorization' => 'Bearer ' . $this->token,
-                       'User-Agent' => 'Cubist TTS Client'], $headers);
-
-               return $this->client->send(new Request($method, $baseURL . ltrim($url, '/'), $headers, $body), $options);
-       }
-
-       protected function checkToken() {
-               if (null !== $this->token && $this->tokenTime > (time() - 540)) {
-                       return true;
-               }
-
-               try {
-
-                       $this->token = $this->client->post('https://' . $this->region . '.api.cognitive.microsoft.com/sts/v1.0/issuetoken',
-                               ['headers' =>
-                                        [
-                                                'Ocp-Apim-Subscription-Key' => $this->key
-                                        ]
-                               ]
-                       )->getBody()->getContents();
-                       return true;
-               } catch (\Exception $e) {
-
-               }
-               return false;
-       }
+class Api
+{
+    /**
+     * @var string
+     */
+    protected $key;
+
+    /**
+     * @var string
+     */
+    protected $region;
+
+    /**
+     * @var null|string
+     */
+    protected $token = null;
+
+    /**
+     * @var int
+     */
+    protected $tokenTime = 0;
+
+
+    /**
+     * @var Client
+     */
+    protected $client;
+
+    public function __construct($key, $region = 'francecentral')
+    {
+        $this->key = $key;
+        $this->region = $region;
+        $this->client = new Client();
+    }
+
+    public function textToSpeech($text, $locale, $gender, $voiceName, $saveToFile)
+    {
+        $ssml = "<speak version='1.0' xmlns='http://www.w3.org/2001/10/synthesis'  xml:lang='$locale'><voice xml:lang='$locale' xml:gender='$gender' name='$voiceName'>";
+        $text = self::stripNonSSMLTags($text);
+        $ssml .= htmlspecialchars($text, ENT_XML1 | ENT_SUBSTITUTE | ENT_QUOTES);
+        $ssml .= "</voice></speak>";
+
+        $this->_call('/v1', 'post', [
+            'X-Microsoft-OutputFormat' => 'audio-48khz-192kbitrate-mono-mp3',
+            'Content-type' => 'application/ssml+xml'
+        ], $ssml, ['sink' => $saveToFile]);
+    }
+
+    public static function stripNonSSMLTags($text, $additional_allowed_tags = '')
+    {
+        return strip_tags($text, '<break><say-as><audio><p><s><sub><mark><prosody><emphasis><par><seq><media><phoneme><voice><lang>' . $additional_allowed_tags);
+    }
+
+    /**
+     * @param $raw
+     * @return array|false
+     */
+    public function listVoices($raw = false)
+    {
+        $cacheKey = 'azure_tts_voices_' . $raw;
+        Cache::forget($cacheKey);
+        return Cache::remember($cacheKey, 86400, function () use ($raw) {
+            return $this->_listVoices($raw);
+        });
+    }
+
+    /**
+     * @param $raw bool
+     * @return array|false
+     */
+    protected function _listVoices($raw = false)
+    {
+        $resp = $this->_call('/voices/list');
+        if (!$resp) {
+            return false;
+        }
+        $j = json_decode($resp->getBody()->getContents(), true);
+        if ($raw) {
+            return $j;
+        }
+        $res = [];
+        foreach ($j as $voice) {
+            $res[$voice['Locale'] . '/' . $voice['Gender'] . '/' . $voice['ShortName']] = $voice['DisplayName'] . ' / ' . $voice['Gender'] . ' / ' . $voice['LocaleName'];
+        }
+        return $res;
+    }
+
+    /**
+     * @param string $url
+     * @param string $method
+     * @param array $headers
+     * @param string|null $body
+     * @param array $options
+     * @return Response|false
+     */
+    protected function _call($url, $method = 'get', $headers = [], $body = null, $options = [])
+    {
+
+        if (!$this->checkToken()) {
+            return false;
+        }
+        $baseURL = 'https://' . $this->region . '.tts.speech.microsoft.com/cognitiveservices/';
+        $headers = array_merge([
+            'Authorization' => 'Bearer ' . $this->token,
+            'User-Agent' => 'Cubist TTS Client'], $headers);
+
+        return $this->client->send(new Request($method, $baseURL . ltrim($url, '/'), $headers, $body), $options);
+    }
+
+    protected function checkToken()
+    {
+        if (null !== $this->token && $this->tokenTime > (time() - 540)) {
+            return true;
+        }
+
+        try {
+
+            $this->token = $this->client->post('https://' . $this->region . '.api.cognitive.microsoft.com/sts/v1.0/issuetoken',
+                ['headers' =>
+                    [
+                        'Ocp-Apim-Subscription-Key' => $this->key
+                    ]
+                ]
+            )->getBody()->getContents();
+            return true;
+        } catch (\Exception $e) {
+
+        }
+        return false;
+    }
 }
\ No newline at end of file