transcribe_google.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. <?php
  2. /**
  3. * transcribe_google class
  4. *
  5. * @method null download
  6. */
  7. if (!class_exists('transcribe_google')) {
  8. class transcribe_google implements transcribe_interface {
  9. /**
  10. * declare private variables
  11. */
  12. private $api_key;
  13. private $api_url;
  14. private $language;
  15. private $alternate_language;
  16. private $application_credentials;
  17. private $path;
  18. private $filename;
  19. private $audio_string;
  20. private $audio_mime_type;
  21. private $format;
  22. private $voice;
  23. private $message;
  24. private $model;
  25. /**
  26. * called when the object is created
  27. */
  28. public function __construct($settings) {
  29. // build the setting object and get the recording path
  30. $this->api_key = $settings->get('transcribe', 'api_key');
  31. $this->api_url = $settings->get('transcribe', 'api_url');
  32. $this->language = $settings->get('transcribe', 'language');
  33. $this->alternate_language = $settings->get('transcribe', 'alternate_language');
  34. $this->application_credentials = $settings->get('transcribe', 'application_credentials');
  35. }
  36. public function set_path(string $audio_path) {
  37. $this->path = $audio_path;
  38. }
  39. public function set_filename(string $audio_filename) {
  40. $this->filename = $audio_filename;
  41. }
  42. public function set_audio_string(string $audio_string) {
  43. $this->audio_string = $audio_string;
  44. }
  45. public function set_audio_mime_type(string $audio_mime_type) {
  46. $this->audio_mime_type = $audio_mime_type;
  47. }
  48. public function set_format(string $audio_format) {
  49. $this->format = $audio_format;
  50. }
  51. public function set_voice(string $audio_voice) {
  52. $this->voice = $audio_voice;
  53. }
  54. public function set_language(string $audio_language) {
  55. $this->language = $audio_language;
  56. }
  57. public function set_translate(string $audio_translate) {
  58. $this->translate = $audio_translate;
  59. }
  60. public function set_message(string $audio_message) {
  61. $this->message = $audio_message;
  62. }
  63. public function is_language_enabled() : bool {
  64. // return the whether engine is handles languages
  65. return false;
  66. }
  67. public function is_translate_enabled() : bool {
  68. // return the whether engine is able to translate
  69. return false;
  70. }
  71. public function get_languages() : array {
  72. // create the languages array
  73. $languages = array(
  74. "af" => "Afrikaans",
  75. "ar" => "Arabic",
  76. "hy" => "Armenian",
  77. "az" => "Azerbaijani",
  78. "be" => "Belarusian",
  79. "bs" => "Bosnian",
  80. "bg" => "Bulgarian",
  81. "ca" => "Catalan",
  82. "zh" => "Chinese",
  83. "hr" => "Croatian",
  84. "cs" => "Czech",
  85. "da" => "Danish",
  86. "nl" => "Dutch",
  87. "en" => "English",
  88. "et" => "Estonian",
  89. "fi" => "Finnish",
  90. "fr" => "French",
  91. "gl" => "Galician",
  92. "de" => "German",
  93. "el" => "Greek",
  94. "he" => "Hebrew",
  95. "hi" => "Hindi",
  96. "hu" => "Hungarian",
  97. "is" => "Icelandic",
  98. "id" => "Indonesian",
  99. "it" => "Italian",
  100. "ja" => "Japanese",
  101. "kn" => "Kannada",
  102. "kk" => "Kazakh",
  103. "ko" => "Korean",
  104. "lv" => "Latvian",
  105. "lt" => "Lithuanian",
  106. "mk" => "Macedonian",
  107. "ms" => "Malay",
  108. "mr" => "Marathi",
  109. "mi" => "Maori",
  110. "ne" => "Nepali",
  111. "no" => "Norwegian",
  112. "fa" => "Persian",
  113. "pl" => "Polish",
  114. "pt" => "Portuguese",
  115. "ro" => "Romanian",
  116. "ru" => "Russian",
  117. "sr" => "Serbian",
  118. "sk" => "Slovak",
  119. "sl" => "Slovenian",
  120. "es" => "Spanish",
  121. "sw" => "Swahili",
  122. "sv" => "Swedish",
  123. "tl" => "Tagalog",
  124. "ta" => "Tamil",
  125. "th" => "Thai",
  126. "tr" => "Turkish",
  127. "uk" => "Ukrainian",
  128. "ur" => "Urdu",
  129. "vi" => "Vietnamese",
  130. "cy" => "Welsh"
  131. );
  132. // return the languages array
  133. return $languages;
  134. }
  135. /**
  136. * transcribe - speech to text
  137. */
  138. public function transcribe() : string {
  139. if (!isset($this->language) && empty($this->language)) {
  140. $this->language = 'en-US';
  141. }
  142. if (!isset($this->alternate_language) && empty($this->alternate_language)) {
  143. $this->alternate_language = 'es-US';
  144. }
  145. // get the content type
  146. if (file_exists($this->path.'/'.$this->filename)) {
  147. $path_array = pathinfo($this->path.'/'.$this->filename);
  148. if ($path_array['extension'] == "mp3") {
  149. $content_type = 'audio/mp3';
  150. }
  151. if ($path_array['extension'] == "wav") {
  152. $content_type = 'audio/wav';
  153. }
  154. }
  155. elseif (!empty($this->audio_string)) {
  156. $content_type = $this->audio_mime_type;
  157. }
  158. // start output buffer
  159. ob_start();
  160. $out = fopen('php://output', 'w');
  161. // version 1
  162. if (trim($this->api_url) == 'https://speech.googleapis.com/v1p1beta1/speech') {
  163. if (isset($this->api_key) && $this->api_key != '') {
  164. if (file_exists($this->path.'/'.$this->filename)) {
  165. //file has been found
  166. }
  167. elseif (!empty($this->audio_string)) {
  168. //if this is empty then use the temp directory
  169. if (empty($this->path)) {
  170. $this->path = sys_get_temp_dir();
  171. }
  172. //save the audio string on the file system
  173. file_put_contents($this->path.'/'.$this->filename, $this->audio_string);
  174. }
  175. else {
  176. //audio file or string not found
  177. return false;
  178. }
  179. //get the length of the audio file
  180. $audio_length = (float)system("soxi -D ".$this->path."/".$this->filename);
  181. // Convert audio file to FLAC format
  182. $flac_file = $this->path . '/' . $this->filename . '.flac';
  183. $command = "sox ".$this->path."/".$this->filename." ".$flac_file;
  184. if ($audio_length > 59) { $command .= " trim 0 00:59"; }
  185. exec($command);
  186. // Base64 encode FLAC file
  187. $flac_base64 = base64_encode(file_get_contents($flac_file));
  188. // Prepare JSON data
  189. $data = [
  190. 'config' => [
  191. 'languageCode' => $this->language,
  192. 'enableWordTimeOffsets' => false,
  193. 'enableAutomaticPunctuation' => true,
  194. 'alternativeLanguageCodes' => $this->alternate_language
  195. ],
  196. 'audio' => [
  197. 'content' => $flac_base64
  198. ]
  199. ];
  200. $json_data = json_encode($data);
  201. // initialize a curl handle
  202. $ch = curl_init();
  203. // set the URL for the request
  204. curl_setopt($ch, CURLOPT_URL, $this->api_url . ':recognize?key=' . $this->api_key);
  205. // set the request method to POST
  206. curl_setopt($ch, CURLOPT_POST, true);
  207. // send the HTTP headers
  208. curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
  209. // send the HTTP post
  210. curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
  211. // return the response as a string instead of outputting it directly
  212. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  213. // run the curl request and transcription message
  214. $response = curl_exec($ch);
  215. // check for errors
  216. if (curl_errno($ch)) {
  217. echo 'Error: ' . curl_error($ch);
  218. exit;
  219. }
  220. // close the handle
  221. curl_close($ch);
  222. // Remove temporary FLAC file
  223. unlink($flac_file);
  224. }
  225. }
  226. // version 2
  227. if (substr($this->api_url, 0, 32) == 'https://speech.googleapis.com/v2') {
  228. if (!empty($this->application_credentials)) {
  229. putenv("GOOGLE_APPLICATION_CREDENTIALS=".$this->application_credentials);
  230. }
  231. // Base64 encode the audio
  232. if (file_exists($this->path.'/'.$this->filename)) {
  233. //file has been found
  234. $audio_base64 = base64_encode(file_get_contents($this->file_path . '/' . $this->file_name));
  235. }
  236. elseif (!empty($this->audio_string)) {
  237. $audio_base64 = base64_encode($this->audio_string);
  238. }
  239. else {
  240. //audio file or string not found
  241. return false;
  242. }
  243. // Prepare JSON data
  244. $data = [
  245. 'config' => [
  246. 'auto_decoding_config' => [],
  247. 'language_codes' => [$this->language],
  248. 'model' => 'long'
  249. ],
  250. 'content' => $audio_base64
  251. ];
  252. $json_data = json_encode($data);
  253. // initialize a curl handle
  254. $ch = curl_init();
  255. // set the URL for the request
  256. curl_setopt($ch, CURLOPT_URL, $this->api_url);
  257. // set the request method to POST
  258. curl_setopt($ch, CURLOPT_POST, 1);
  259. // send the HTTP headers
  260. curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: Bearer ' . shell_exec('gcloud auth application-default print-access-token')]);
  261. // send the HTTP post
  262. curl_setopt($ch, CURLOPT_POSTFIELDS, $json_data);
  263. // return the response as a string instead of outputting it directly
  264. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  265. //add verbose for debugging
  266. curl_setopt($ch, CURLOPT_VERBOSE, true);
  267. curl_setopt($ch, CURLOPT_STDERR, $out);
  268. // run the curl request and transcription message
  269. $response = curl_exec($ch);
  270. // check for errors
  271. if (curl_errno($ch)) {
  272. echo 'Error: ' . curl_error($ch);
  273. exit;
  274. }
  275. // close the handle
  276. curl_close($ch);
  277. }
  278. // validate the json
  279. if (!empty($response)) {
  280. $ob = json_decode($response);
  281. if($ob === null) {
  282. echo "invalid json\n";
  283. return false;
  284. }
  285. $json = json_decode($response, true);
  286. // echo "json; ".$json."\n";
  287. $message = '';
  288. foreach($json['results'] as $row) {
  289. $this->message .= $row['alternatives'][0]['transcript'];
  290. }
  291. }
  292. // show the debug information
  293. fclose($out);
  294. // $this->debug = ob_get_clean();
  295. // return the transcription
  296. if (empty($this->message)) {
  297. return '';
  298. }
  299. else {
  300. return $this->message;
  301. }
  302. }
  303. }
  304. }
  305. ?>