{"id":354242,"date":"2024-05-20T22:44:30","date_gmt":"2024-05-20T22:44:30","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=354242"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=354242","title":{"rendered":"<span>\u0423\u0447\u0438\u043c \u0418\u0418 \u0447\u0430\u0442\u0431\u043e\u0442\u0430 \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u0434\u043b\u044f \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0430. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0444\u043e\u0440\u043c\u0430\u0442 \u0447\u0430\u0442\u0430 \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0418\u0418. \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0447\u0430\u0442 \u0433\u0440\u0435\u0435\u0442 \u043c\u043e\u044e \u0438\u043d\u0442\u0440\u043e\u0432\u0435\u0440\u0442\u0438\u0432\u043d\u0443\u044e \u0434\u0443\u0448\u0443, \u0432\u0437\u0440\u0430\u0449\u0435\u043d\u043d\u0443\u044e \u043d\u0430 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A4%D0%B8%D0%B4%D0%BE%D0%BD%D0%B5%D1%82\" rel=\"noopener noreferrer nofollow\">BBS&#8217;\u043a\u0430\u0445<\/a> \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0445 \u043e <a href=\"http:\/\/lib.ru\/ANEKDOTY\/9600.txt\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0448BOFH<\/a>. \u041d\u043e, \u0432\u0441\u0451 \u0436\u0435, \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u0442\u0430\u043c\u0438 \u0431\u043e\u043b\u0435\u0435 &#171;\u0447\u0435\u043b\u043e\u0432\u0435\u0447\u043d\u044b\u043c&#187;, \u043d\u0430\u0443\u0447\u0438\u0442\u044c \u0438\u0445 \u0441\u043b\u0443\u0448\u0430\u0442\u044c, \u0441\u043b\u044b\u0448\u0430\u0442\u044c \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c? \u0412\u0441\u0451, \u043e \u0447\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0438\u043b\u043b\u0435\u0440-\u0444\u0438\u0447\u0435\u0439, \u0438 \u0434\u0430\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u044b \u043a \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443 (LLM). \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0445 \u043d\u0430 <em>Python<\/em>, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0436\u0435\u043b\u0430\u044e\u0449\u0435\u0433\u043e.<\/p>\n<h2>openai.Audio.transcribe<\/h2>\n<p>\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 ChatGPT \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e LLM \u0434\u0432\u0438\u0436\u043a\u0430. \u0415\u0441\u043b\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0435\u0433\u043e <a href=\"https:\/\/platform.openai.com\/docs\/introduction\" rel=\"noopener noreferrer nofollow\">API<\/a>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c <strong>whisper-1,<\/strong> \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0443\u044e \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0437\u0430 \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u043f\u0446\u0438\u044e \u0442\u0435\u043a\u0441\u0442\u0430. \u0412\u0441\u0451, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0432\u0430\u0448 \u0433\u043e\u043b\u043e\u0441 \u0432 \u0442\u0435\u043a\u0441\u0442, \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>openai.Audio.atranscribe<\/strong>. \u0417\u0434\u0435\u0441\u044c \u0438 \u0434\u0430\u043b\u0435\u0435 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<pre><code class=\"python\">    import openai       async def transcript(file, prompt=None, language=\"en\", response_format=\"text\"):         \"\"\"         Wrapper for the transcribe function. Returns only the content of the message.          :param file: Path with filename to transcript.         :param prompt: Previous prompt. Default is None.         :param language: Language on which audio is. Default is 'en'.         :param response_format: default response format, by default is 'text'.                                Possible values are: json, text, srt, verbose_json, or vtt.           :return: transcription (text, json, srt, verbose_json or vtt)         \"\"\"         kwargs = {}         if prompt is not None:             kwargs[\"prompt\"] = prompt         return await openai.Audio.atranscribe(             model=\"whisper-1\",             file=file,             language=language,             response_format=response_format,             temperature=1,             **kwargs,         )<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0435\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<pre><code class=\"python\">    with open(file_path, \"rb\") as f:         transcript = await transcript(file=f, language=\"en\")     response = await ask_chat(transcript)  # this method is for prompting LLM using pure string<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b &#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0442\u044b \u043a\u0430\u0440\u0442\u0438\u043d\u044b \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0433\u043e\u043b\u043e\u0441 \u043d\u0430\u043b\u0435\u0442\u0443?\u00a0<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>sounddevice<\/strong>. \u0422\u0430\u043a \u043a\u0430\u043a <strong>sounddevice<\/strong> \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <em>wav<\/em>, \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u0435\u0433\u043e \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 <em>mp3<\/em>, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong>pydab<\/strong>. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">import os import tempfile import uuid  import sounddevice as sd import soundfile as sf from pydub import AudioSegment   def record_and_convert_audio(duration: int = 5, frequency_sample: int = 16000):     \"\"\"     Records audio for a specified duration and converts it to MP3 format.          This function records audio for a given duration (in seconds) with a specified frequency sample.     The audio is then saved as a temporary .wav file, converted to .mp3 format, and the .wav file is deleted.     The function returns the path to the .mp3 file.          :param duration: The duration of the audio recording in seconds. Default is 5 seconds.     :param frequency_sample: The frequency sample rate of the audio recording. Default is 16000 Hz.          :return: The path to the saved .mp3 file.     \"\"\"     print(f\"Listening beginning for {duration}s...\")     recording = sd.rec(int(duration * frequency_sample), samplerate=frequency_sample, channels=1)     sd.wait()  # Wait until recording is finished     print(\"Recording complete!\")     temp_dir = tempfile.gettempdir()     wave_file = f\"{temp_dir}\/{str(uuid.uuid4())}.wav\"     sf.write(wave_file, recording, frequency_sample)     print(f\"Temp audiofile saved: {wave_file}\")     audio = AudioSegment.from_wav(wave_file)     os.remove(wave_file)     mp3_file = f\"{temp_dir}\/{str(uuid.uuid4())}.mp3\"     audio.export(mp3_file, format=\"mp3\")     print(f\"Audio converted to MP3 and stored into {mp3_file}\")     return mp3_file<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438. \u041d\u043e \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u0442\u043e\u043f\u043e\u0440\u043d\u044b\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0432\u044b \u0434\u043e\u043b\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435 &#8212; \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u0438 \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0436\u0434\u0430\u0442\u044c \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043e\u0431\u0440\u0435\u0437\u043a\u0435 \u0444\u0440\u0430\u0437\u044b. \u041e\u0431\u044b\u0447\u043d\u043e \u0441\u0430\u043c\u044b\u043c \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <em>push-to-talk<\/em>. \u041f\u043e\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443, \u0438\u0434\u0451\u0442 \u0437\u0430\u043f\u0438\u0441\u044c. \u0422\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043e\u043d\u043b\u0430\u0439\u043d \u0447\u0430\u0442\u044b. \u041d\u043e \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e &#171;\u0447\u0435\u043b\u043e\u0432\u0435\u0447\u043d\u044b\u043c&#187; \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e \u0443\u0448\u0438 \u0418\u0418. \u041c\u043d\u0435, \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u0431\u044b\u043b\u043e \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043a\u043d\u043e\u043f\u043e\u043a, \u0438, \u043f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0451\u0442\u0443, \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0443 \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u0434\u0443: \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e, \u0438 \u0435\u0441\u043b\u0438 \u0432 \u0448\u0443\u043c\u0435 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u0430 \u0440\u0435\u0447\u044c, \u0442\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u0435\u0451. \u041d\u0443, \u043f\u043e\u0447\u0442\u0438 \u0442\u0430\u043a, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <em>Google Assistant<\/em>, <em>Siri<\/em> \u0438 \u0443\u043c\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0430-\u043b\u044f \u0410\u043b\u0438\u0441\u0430 \u0432 \u0432\u0430\u0448\u0435\u043c \u0434\u043e\u043c\u0435. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0437\u0432\u0443\u043a, \u0432\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448\u0443 catch-\u0444\u0440\u0430\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u0439 (\u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438).<\/p>\n<pre><code class=\"python\">import re  pattern = r\"hellos*,?s*bunny\" if re.match(pattern, transcript, re.IGNORECASE):     prompt = re.sub(pattern, '', text, flags=re.IGNORECASE).lstrip()     response = await ask_chat(prompt)<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0436, \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u043e\u0439 <strong>AudioRecorde<\/strong>r, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 <strong>pyaudio<\/strong>. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d \u0438 \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0443\u043c (\u0440\u0435\u0447\u044c) \u043d\u0430 \u0444\u043e\u043d\u0435 \u0442\u0438\u0448\u0438\u043d\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B5_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0441\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435<\/a>. \u041f\u043e\u043b\u043d\u0430\u044f \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import math import os import struct import tempfile import time import uuid import wave  import pyaudio from pydub import AudioSegment   class AudioRecorder:     \"\"\"     The AudioRecorder class is for managing an instance of the audio recording and conversion process.      Parameters:     pyaudio_obj (PyAudio): Instance of PyAudio. Default is pyaudio.PyAudio().     threshold (int): The RMS threshold for starting the recording. Default is 15.     channels (int): The number of channels in the audio stream. Default is 1.     chunk (int): The number of frames per buffer. Default is 1024.     f_format (int): The format of the audio stream. Default is pyaudio.paInt16.     rate (int): The sample rate of the audio stream. Default is 16000 Hz.     sample_width (int): The sample width (in bytes) of the audio stream. Default is 2.     timeout_length (int): The length of the timeout for the recording (in seconds). Default is 2 seconds.     temp_dir (str): The directory for storing the temporary .wav and .mp3 files. Default is the system's temporary dir.     normalize (float): The normalization factor for the audio samples. Default is 1.0 \/ 32768.0.     pa_input (bool): Specifies whether the stream is an input stream. Default is True.     pa_output (bool): Specifies whether the stream is an output stream. Default is True.     \"\"\"      def __init__(         self,         pyaudio_obj=pyaudio.PyAudio(),         threshold=15,         channels=1,         chunk=1024,         f_format=pyaudio.paInt16,         rate=16000,         sample_width=2,         timeout_length=2,         temp_dir=tempfile.gettempdir(),         normalize=(1.0 \/ 32768.0),         pa_input=True,         pa_output=True,     ):         \"\"\"         General init.          This method initializes an instance of the AudioRecorder class with the specified parameters.         The default values are used for any parameters that are not provided.          :param pyaudio_obj: Instance of PyAudio. Default is pyaudio.PyAudio().         :param threshold: The RMS threshold for starting the recording. Default is 15.         :param channels: The number of channels in the audio stream. Default is 1.         :param chunk: The number of frames per buffer. Default is 1024.         :param f_format: The format of the audio stream. Default is pyaudio.paInt16.         :param rate: The sample rate of the audio stream. Default is 16000 Hz.         :param sample_width: The sample width (in bytes) of the audio stream. Default is 2.         :param timeout_length: The length of the timeout for the recording (in seconds). Default is 2 seconds.         :param temp_dir: The directory for storing the temporary .wav and .mp3 files. Default is temp dir.         :param normalize: The normalization factor for the audio samples. Default is 1.0 \/ 32768.0.         :param pa_input: Specifies whether the stream is an input stream. Default is True.         :param pa_output: Specifies whether the stream is an output stream. Default is True.         \"\"\"         self.___pyaudio = pyaudio_obj         self.___threshold = threshold         self.___channels = channels         self.___chunk = chunk         self.___format = f_format         self.___rate = rate         self.___sample_width = sample_width         self.___timeout_length = timeout_length         self.___temp_dir = temp_dir         self.___normalize = normalize         self.___input = pa_input         self.___output = pa_output         self.stream = self.init_stream(             f_format=self.___format,             channels=self.___channels,             rate=self.___rate,             pa_input=self.___input,             pa_output=self.___output,             frames_per_buffer=self.___chunk,         )      def init_stream(self, f_format, channels, rate, pa_input, pa_output, frames_per_buffer):         \"\"\"         Initializes an audio stream with the specified parameters.          This function uses PyAudio to open an audio stream with the given format, channels, rate, input, output,         and frames per buffer.          :param f_format: The format of the audio stream.         :param channels: The number of channels in the audio stream.         :param rate: The sample rate of the audio stream.         :param pa_input: Specifies whether the stream is an input stream. A true value indicates an input stream.         :param pa_output: Specifies whether the stream is an output stream. A true value indicates an output stream.         :param frames_per_buffer: The number of frames per buffer.         :type frames_per_buffer: int          :return: The initialized audio stream.         \"\"\"         return self.___pyaudio.open(             format=f_format,             channels=channels,             rate=rate,             input=pa_input,             output=pa_output,             frames_per_buffer=frames_per_buffer,         )      def record(self):         \"\"\"         Starts recording audio when noise is detected.          This function starts recording audio when noise above a certain threshold is detected.         The recording continues for a specified timeout length.         The recorded audio is then saved as a .wav file, converted to .mp3 format, and the .wav file is deleted.         The function returns the path to the .mp3 file.          :return: The path to the saved .mp3 file.         \"\"\"         print(\"Noise detected, recording beginning\")         rec = []         current = time.time()         end = time.time() + self.___timeout_length          while current &lt;= end:             data = self.stream.read(self.___chunk)             if self.rms(data) >= self.___threshold:                 end = time.time() + self.___timeout_length              current = time.time()             rec.append(data)         filename = self.write(b\"\".join(rec))         return self.convert_to_mp3(filename)      def write(self, recording):         \"\"\"         Saves the recorded audio to a .wav file.          This function saves the recorded audio to a .wav file with a unique filename.         The .wav file is saved in the specified temporary directory.          :param recording: The recorded audio data.          :return: The path to the saved .wav file.         \"\"\"         filename = os.path.join(self.___temp_dir, f\"{str(uuid.uuid4())}.wav\")          wave_form = wave.open(filename, \"wb\")         wave_form.setnchannels(self.___channels)         wave_form.setsampwidth(self.___pyaudio.get_sample_size(self.___format))         wave_form.setframerate(self.___rate)         wave_form.writeframes(recording)         wave_form.close()         return filename      def convert_to_mp3(self, filename):         \"\"\"         Converts a .wav file to .mp3 format.          This function converts a .wav file to .mp3 format. The .wav file is deleted after the conversion.         The .mp3 file is saved with a unique filename in the specified temporary directory.          :param filename: The path to the .wav file to be converted.          :return: The path to the saved .mp3 file.         \"\"\"         audio = AudioSegment.from_wav(filename)         mp3_file_path = os.path.join(self.___temp_dir, f\"{str(uuid.uuid4())}.mp3\")         audio.export(mp3_file_path, format=\"mp3\")         os.remove(filename)         return mp3_file_path      def listen(self):         \"\"\"         Starts listening for audio.          This function continuously listens for audio and starts recording when the         RMS value of the audio exceeds a certain threshold.          :return: The path to the saved .mp3 file if recording was triggered.         \"\"\"         print(\"Listening beginning...\")         while True:             mic_input = self.stream.read(self.___chunk)             rms_val = self.rms(mic_input)             if rms_val > self.___threshold:                 return self.record()      def rms(self, frame):         \"\"\"         Calculates the Root Mean Square (RMS) value of the audio frame.          This function calculates the RMS value of the audio frame, which is a measure of the power in the audio signal.          :param frame: The audio frame for which to calculate the RMS value.          :return: The RMS value of the audio frame.         \"\"\"         count = len(frame) \/ self.___sample_width         f_format = \"%dh\" % count         shorts = struct.unpack(f_format, frame)          sum_squares = 0.0         for sample in shorts:             normal_sample = sample * self.___normalize             sum_squares += normal_sample * normal_sample         rms = math.pow(sum_squares \/ count, 0.5)          return rms * 1000<\/code><\/pre>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0434\u043e\u0431\u0440\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b <em>threshold<\/em>, <em>timeout<\/em>, <em>channels<\/em>, <em>sample_length<\/em>, <em>chunk<\/em> \u0438 <em>rate<\/em> \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d\u0430. \u041d\u0443 \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043a\u043e\u0434, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<pre><code class=\"python\">from utils.audio_recorder import AudioRecorder  file_path = AudioRecorder().listen()<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>speech_recognition<\/h2>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0442 <em>OpenAI<\/em> \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e, \u043d\u043e \u0442\u043e\u043a\u0435\u043d\u044b \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0447\u0442\u043e\u0431\u044b \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0435, \u0438, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434. \u041b\u0438\u0431\u043e \u0432\u043e\u0432\u0441\u0435 \u0432\u0430\u043c \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <em>llama2<\/em> \u0438\u043b\u0438\u00a0 <em>Bard<\/em> \u0432\u043c\u0435\u0441\u0442\u043e <em>ChatGPT<\/em>.\u00a0 \u0422\u043e\u0433\u0434\u0430 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 <strong>speech_recognition<\/strong>. \u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0438\u0435 \u043e\u0442 <em>Google<\/em>, \u043d\u043e \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433\u0438\u0435 \u0434\u0432\u0438\u0436\u043a\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <em>wit<\/em>, <em>azure<\/em>, <em>sphinx<\/em>. \u0412 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435 \u0435\u0441\u0442\u044c \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b, \u0442\u0430\u043a \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441 <strong>Microphone()<\/strong>. \u0422\u0430\u043a \u0436\u0435 \u043a\u0430\u043a \u0438 \u043c\u043e\u0439 AudioRecorder, \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e \u043f\u043e \u0433\u043e\u043b\u043e\u0441\u0443. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435, \u0447\u0442\u043e \u0432\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u044d\u0442\u043e \u044f\u0437\u044b\u043a \u0430\u0443\u0434\u0438\u043e\u0444\u0430\u0439\u043b\u0430. \u0414\u0430, \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0433\u0438\u0431\u043a\u043e \u0438 \u0443\u0434\u043e\u0431\u043d\u043e, \u043a\u0430\u043a \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 \u043e\u0442 <em>OpenAI<\/em>, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e \u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <em>language<\/em> \u0438 \u043d\u0430\u0434\u0435\u044f\u0442\u0441\u044f, \u0447\u0442\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u0430\u043c\u0430 \u0432\u044b\u0431\u0435\u0440\u0435\u0442 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u043d\u043e \u044f \u0431\u044b \u043b\u0438\u0447\u043d\u043e \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u043b \u043d\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u044f\u0437\u044b\u043a \u0432\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u0435 \u043e\u0448\u0438\u0431\u043e\u043a. \u041f\u0440\u0438\u043c\u0435\u0440\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">import speech_recognition as sr   class CustomTranscriptor:     \"\"\"     This is wrapper class for Google Transcriptor which uses microphone to get audio sample.     \"\"\"      def __init__(self, language=\"en-EN\"):         \"\"\"         General init.          :param language: Language, what needs to be transcripted.         \"\"\"         self.___recognizer = sr.Recognizer()         self.___source = sr.Microphone()         self.language = language          def transcript(self):     \"\"\"     This function transcripts audio (from microphone recording) to text using Google transcriptor.      :return: transcripted text (string).     \"\"\"     print(\"Listening beginning...\")     with self.___source as source:         audio = self.___recognizer.listen(source, timeout=5)      user_input = None     try:         user_input = self.___recognizer.recognize_google(audio, language=self.language)     except sr.UnknownValueError:         print(\"Google Speech Recognition can't transcript audio\")     except sr.RequestError as error:         print(f\"Unable to fetch from resource Google Speech Recognition: {error}\")     except sr.WaitTimeoutError as error:         print(f\"Input timeout, only silence is get: {error}\")     return user_input<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043a\u043e\u0434 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0447\u0430\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0433\u043e\u043b\u043e\u0441 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">import asyncio  from utils.audio_recorder import AudioRecorder from utils.transcriptors import CustomTranscriptor   method = \"google\"  # or any to use speech_recognition instead of openai   async def main():     while True:         try:             if \"google\" not in method:                 file_path = AudioRecorder().listen()                 with open(file_path, \"rb\") as f:                     transcript = await gpt.transcript(file=f, language=\"en\")             else:                 transcript = CustomTranscriptor(language=\"en-US\").transcript()             if transcript:                 print(transcript)                 response = await ask_chat(transcript)         except KeyboardInterrupt:             break               asyncio.run(main())<\/code><\/pre>\n<h2>\u0422\u0435\u043a\u0441\u0442-\u0432-\u0440\u0435\u0447\u044c<\/h2>\n<p>\u041d\u0430\u0441\u0442\u0430\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0443\u0447\u0438\u0442\u044c \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043d\u0430\u0448 \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442. \u0417\u0434\u0435\u0441\u044c, \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043d\u0435\u0442 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438, \u0435\u0441\u043b\u0438 \u0432\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442\u0435 c LLM \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e. \u0414\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u0433\u043e\u043b\u043e\u0441 \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u043d\u0443 \u0438\u0437 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0439 TTS.\u00a0<\/p>\n<p>\u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <strong>gtts<\/strong> \u043e\u0442 <em>Google<\/em>. \u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, <strong>gtts<\/strong> \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0444\u0430\u0439\u043b \u0441 \u043e\u0437\u0432\u0443\u0447\u043a\u043e\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0432 \u043a\u0430\u043a\u043e\u043c-\u043b\u0438\u0431\u043e \u043f\u043b\u0435\u0435\u0440\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0443\u0434\u0430\u043b\u0438\u0442\u044c. \u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <strong>pydub.playback<\/strong>.<\/p>\n<pre><code class=\"python\">import os import tempfile from uuid import uuid4  from gtts import gTTS from pydub import AudioSegment, playback   def process_via_gtts(text):     temp_dir = tempfile.gettempdir()     tts = gTTS(text, lang=\"en\")     raw_file = f\"{temp_dir}\/{str(uuid4())}.mp3\"     tts.save(raw_file)     audio = AudioSegment.from_file(raw_file, format=\"mp3\").speedup(1.3)  # haste a bit     os.remove(raw_file)     playback.play(audio)<\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 &#8212; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <strong>pyttsx<\/strong>. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 <strong>gtts<\/strong>, \u0441\u0438\u043d\u0442\u0435\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0447\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u043b\u0435\u0442\u0443 \u0432 \u0446\u0438\u043a\u043b\u0435, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0439 \u0442\u0440\u0430\u043d\u0441\u043b\u044f\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430. \u041d\u0443 \u0438 \u043f\u043b\u044e\u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043a \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443.<\/p>\n<pre><code class=\"python\">from time import sleep  from pyttsx4 import init as pyttsx_init   def process_via_pytts(text):     \"\"\"     Converts text to speach using python-tts text-to-speach method      :param text: Text needs to be converted to speach.     \"\"\"     engine = pyttsx_init()     engine.setProperty(\"voice\", 'com.apple.voice.enhanced.ru-RU.Katya')     engine.say(text)     engine.startLoop(False)      while engine.isBusy():         engine.iterate()         sleep(0.1)      engine.endLoop()<\/code><\/pre>\n<p>\u041e\u0437\u0432\u0443\u0447\u043a\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 \u0433\u043e\u043b\u043e\u0441\u0430\u043c\u0438, \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0433\u043e\u043b\u043e\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">engine = pyttsx_init() engine.getProperty(\"voices\")<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0432\u043e\u0435\u0434\u0438\u043d\u043e, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0442\u0432\u0435\u0442 \u043e\u0442 \u0447\u0430\u0442\u0430 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e tts \u0434\u0432\u0438\u0436\u043e\u043a.<\/p>\n<pre><code class=\"python\">import asyncio  from utils.audio_recorder import AudioRecorder from utils.transcriptors import CustomTranscriptor from utils.tts import process_via_gtts, process_via_pytts   async def tts_process(text, method):     \"\"\"     Converts text to speach using pre-defined model      :param text: Text needs to be converted to speach.     :param method: method of tts     \"\"\"     if \"google\" in method:         process_via_gtts(text)     else:         process_via_pytts(text)           async def main():     method = \"google\"     while True:         try:             if \"google\" not in method:                 file_path = AudioRecorder().listen()                 with open(file_path, \"rb\") as f:                     transcript = await gpt.transcript(file=f, language=\"en\")             else:                 transcript = CustomTranscriptor(language=\"en-US\").transcript()             if transcript:                 print(transcript)                 response = await ask_chat(transcript)  # this method returns string of whole chatbot response                 await tts_process(response, \"not google\")         except KeyboardInterrupt:             break               asyncio.run(main())<\/code><\/pre>\n<h2>\u041d\u044e\u0430\u043d\u0441\u044b \u0447\u0435\u043b\u043e\u0432\u0435\u0447\u043d\u043e\u0441\u0442\u0438<\/h2>\n<p>\u041a\u0430\u043a \u0432 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0430\u043d\u0435\u043a\u0434\u043e\u0442\u0435 \u043f\u0440\u043e \u0427\u0430\u043f\u0430\u0435\u0432\u0430: &#171;\u043d\u043e \u0435\u0441\u0442\u044c \u043e\u0434\u0438\u043d \u043d\u044e\u0430\u043d\u0441&#187;. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0447\u0430\u0442-\u0431\u043e\u0442\u0430 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u0430\u043a\u043e\u0435-\u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043c\u043e\u0434\u0435\u043b\u0438, \u043e\u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 tts \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0434\u043e\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u0438 \u043d\u0430\u0447\u0430\u0442\u044c \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0433\u043e\u043b\u043e\u0441\u0430, \u0447\u0442\u043e \u0435\u0449\u0451 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430. \u041a\u043e\u0433\u0434\u0430 \u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u043b \u0441\u0432\u043e\u0438 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u044b, \u044d\u0442\u043e \u0440\u0443\u0448\u0438\u043b\u043e \u0432\u0441\u044e \u043c\u0430\u0433\u0438\u044e \u0436\u0438\u0432\u043e\u0433\u043e \u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u043b\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0434\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c\u0441\u044f \u043a \u0441\u0442\u0430\u0440\u043e\u043c\u0443-\u0434\u043e\u0431\u0440\u043e\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c\u0443 \u043e\u0431\u0449\u0435\u043d\u0438\u044e. \u041d\u043e \u043d\u0435 \u0432\u0441\u0451 \u0442\u0430\u043a \u043f\u043b\u043e\u0445\u043e. \u0421\u043a\u0430\u0436\u0443 \u043f\u043e \u043f\u0440\u0430\u0432\u0434\u0435, \u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043b\u044e\u0431\u043b\u0451\u043d \u0432 \u043c\u0435\u0442\u043e\u0434 <em>stream<\/em> \u0432 <em>ChatGPT<\/em>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u043d\u0430\u043b\u0435\u0442\u0443 \u0438\u0437 <strong>ChatCompletion<\/strong>. \u0422\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u044f \u0438\u0434\u0435\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c tts \u0441\u0440\u0430\u0437\u0443, \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u0432 \u043e\u0442\u0432\u0435\u0442\u0435 \u043e\u0442 \u0431\u043e\u0442\u0430. \u041d\u043e \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u0442\u0435, \u043a\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u044d\u0442\u043e\u0439 \u0444\u0438\u0447\u0435\u0439, \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0436\u0435\u0442 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e &#8212; \u043a\u0430\u043a \u0441\u043b\u043e\u0432\u0430, \u0442\u0430\u043a \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u0443\u043a\u0432\u044b. \u0418 \u044d\u0442\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u0435\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u044b\u0442\u0430\u0435\u0442\u0435\u0441\u044c \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c tts \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0439 <em>chunk<\/em>.\u00a0<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"json\">{   \"id\": \"chatcmpl-ABCABC\",   \"object\": \"chat.completion.chunk\",   \"created\": 1234567890,   \"model\": \"gpt-3.5-turbo\",   \"choices\": [     {       \"index\": 0,       \"delta\": {         \"content\": \"Hel\"       },       \"finish_reason\": null     }   ] }  {   \"id\": \"chatcmpl-ABCABC\",   \"object\": \"chat.completion.chunk\",   \"created\": 1234567890,   \"model\": \"gpt-3.5-turbo\",   \"choices\": [     {       \"index\": 1,       \"delta\": {         \"content\": \"lo, \"       },       \"finish_reason\": null     }   ] } &lt;...>  {   \"id\": \"chatcmpl-ABCABC\",   \"object\": \"chat.completion.chunk\",   \"created\": 1234567890,   \"model\": \"gpt-3.5-turbo\",   \"choices\": [     {       \"index\": 12,       \"delta\": {         \"content\": \"ay?\"       },       \"finish_reason\": null     }   ] } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0435\u0440\u0432\u0430\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f: \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0436\u0438\u0434\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0446\u0435\u043b\u043e\u0433\u043e \u0441\u043b\u043e\u0432\u0430, \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u043e\u0437\u0432\u0443\u0447\u043a\u0443.<\/p>\n<pre><code class=\"python\">import string import sys  from utils.tts import tts_process   async def ask_chat(user_input):     full_response = \"\"     word = \"\"     async for response in gpt.str_chat(user_input):         for char in response:             word += char             if char in string.whitespace or char in string.punctuation:                 if word:                     tts_process(word)                     word = \"\"             sys.stdout.write(char)  # I use direct stdout output to make output be printed on-the-fly.             sys.stdout.flush()      # To get typewriter effect I forcefully flush output each time.             full_response += char     print(\"\\n\")     return full_response   # if we'll need whole prompt for some reasons later<\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442, \u0447\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u0442\u0430\u043a \u0441\u0435\u0431\u0435 &#8212; \u0440\u0432\u0430\u043d\u044b\u043c. \u041f\u043e\u0436\u0430\u043b\u0443\u0439, \u043d\u0435\u043f\u043b\u043e\u0445\u043e\u0439 \u0438\u0434\u0435\u0435\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u0436\u0438\u0434\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0441\u043b\u043e\u0432, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 2-3 \u0438 \u043e\u0437\u0432\u0443\u0447\u0438\u0432\u0430\u0442\u044c \u0438\u0445. \u0421\u043b\u043e\u0432\u0430 \u0431\u0443\u0434\u0435\u043c \u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0432 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435.<\/p>\n<pre><code class=\"python\">import string import sys  import asyncio  from utils.tts import tts_process   prompt_queue = asyncio.Queue()   async def ask_chat(user_input):     full_response = \"\"     word = \"\"     async for response in gpt.str_chat(user_input):         for char in response:             word += char             if char in string.whitespace or char in string.punctuation:                 if word:                     await prompt_queue.put(word)                     word = \"\"             sys.stdout.write(char)  # I use direct stdout output to make output be printed on-the-fly.             sys.stdout.flush()      # To get typewriter effect I forcefully flush output each time.             full_response += char     print(\"\\n\")     return full_response   # if we'll need whole prompt for some reasons later   async def tts_task():     limit = 3     empty_counter = 0     while True:         if prompt_queue.empty():             empty_counter += 1         if empty_counter >= 3:             limit = 3             empty_counter = 0         words = []         # Get all available words         limit_counter = 0         while len(words) &lt; limit:             print(len(words))             try:                 word = await asyncio.wait_for(prompt_queue.get(), timeout=1)                 words.extend(word.split())                 if len(words) >= limit:                     break             except asyncio.TimeoutError:                 limit_counter += 1                 if limit_counter >= 10:                     limit = 1          # If we have at least limit words or queue was empty 3 times, process them         if len(words) >= limit:             text = \" \".join(words)             await tts.process(text)             limit = 1  async def main():         asyncio.create_task(tts_task())         # and rest of the code<\/code><\/pre>\n<p>\u042d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u0443\u0436\u0435 \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0442\u0435\u0440\u044f\u044e\u0442\u0441\u044f \u0438\u043d\u0442\u043e\u043d\u0430\u0446\u0438\u0438 \u0438 \u0437\u043d\u0430\u043a\u0438 \u043f\u0440\u0435\u043f\u0438\u043d\u0430\u043d\u0438\u044f. \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u043e, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0447\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043d\u0443 \u0438\u043b\u0438 \u0438\u0445 \u0447\u0430\u0441\u0442\u0438, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0443\u0441\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c\u0438 &#171;<em>.?!,;:<\/em>&#171;.<\/p>\n<pre><code class=\"python\">import string import sys  import asyncio  from utils.tts import tts_process   prompt_queue = asyncio.Queue()   async def ask_chat(user_input):     full_response = \"\"     word = \"\"     async for response in gpt.str_chat(user_input):         for char in response:             word += char             if char in string.whitespace or char in string.punctuation:                 if word:                     await prompt_queue.put(word)                     word = \"\"             sys.stdout.write(char)  # I use direct stdout output to make output be printed on-the-fly.             sys.stdout.flush()      # To get typewriter effect I forcefully flush output each time.             full_response += char     print(\"\\n\")     return full_response   # if we'll need whole prompt for some reasons later     async def tts_sentence_task():     punctuation_marks = \".?!,;:\"     sentence = \"\"     while True:         try:             word = await asyncio.wait_for(prompt_queue.get(), timeout=0.5)             sentence += \" \" + word             # If the last character is a punctuation mark, process the sentence             if sentence[-1] in punctuation_marks:                 await tts_process(sentence)                 sentence = \"\"         except Exception as error:             pass  async def main():     asyncio.create_task(tts_sentence_task())     # and rest of the code<\/code><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u0442\u0435 \u043c\u043e\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0442\u043e \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0437\u0432\u0443\u0447\u043a\u0438 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0432\u043e\u0434 \u0447\u0430\u0442\u0430. \u0427\u0442\u043e\u0431\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u044d\u0442\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c tts \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0442\u043e\u0440\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043b\u044f tts. \u0418 \u0437\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u0435\u0449\u0451 \u043e\u0434\u043d\u0443 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430.<\/p>\n<pre><code class=\"python\">import string import sys  import asyncio  from utils.tts import tts_process   prompt_queue = asyncio.Queue() tts_queue = asyncio.Queue()   async def ask_chat(user_input):     # same       async def tts_sentence_task(): punctuation_marks = \".?!,;:\" sentence = \"\" while True:     try:         word = await asyncio.wait_for(prompt_queue.get(), timeout=0.5)         sentence += \" \" + word         # If the last character is a punctuation mark, process the sentence         if sentence[-1] in punctuation_marks:             await tts_queue.put(sentence)             sentence = \"\"     except Exception as error:         pass   async def tts_worker():     while True:         sentence = await tts_queue.get()         if sentence:             await tts_process(sentence)             tts_queue.task_done()               async def main():     asyncio.create_task(tts_sentence_task())     asyncio.create_task(tts_worker())     # and rest of the code <\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0435 \u0440\u0435\u0448\u0435\u043d\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u0443\u0432\u044b, \u043c\u0435\u0442\u043e\u0434\u044b tts (\u0447\u0442\u043e <strong>gtts<\/strong>, \u0447\u0442\u043e <strong>pyttsx<\/strong>) \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c\u0438. \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442, \u0447\u0442\u043e \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u043e\u0437\u0432\u0443\u0447\u043a\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f, \u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u0427\u0442\u043e\u0431\u044b \u0440\u0435\u0448\u0438\u0442\u044c \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443, \u0441\u043b\u0435\u0434\u0443\u0435\u0442, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043f\u043b\u0435\u0435\u0440\u044b \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u0430\u0445. \u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 <strong>threading<\/strong>.<\/p>\n<pre><code class=\"python\">import threading   async def process_via_gtts(text): \"\"\" Converts text to speach using gtts text-to-speach method  :param text: Text needs to be converted to speach. \"\"\"     temp_dir = tempfile.gettempdir()     tts = gTTS(text, lang=\"en\")     raw_file = f\"{temp_dir}\/{str(uuid4())}.mp3\"     tts.save(raw_file)     audio = AudioSegment.from_file(raw_file, format=\"mp3\").speedup(1.3)     os.remove(raw_file)     player_thread = threading.Thread(target=playback.play(audio), args=(audio,))     player_thread.start()  async def tts_process(text): \"\"\" Converts text to speach using pre-defined model  :param text: Text needs to be converted to speach. \"\"\" if \"google\" in self.___method:     await self.__process_via_gtts(text) else:     player_thread = threading.Thread(target=process_via_pytts, args=(text,))     player_thread.start()<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 &#8212; \u0442\u0435\u043f\u0435\u0440\u044c tts \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u043d\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435. \u0415\u0441\u043b\u0438 \u043a \u0442\u043e\u043c\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u043f\u043e\u043a\u0430 \u043e\u0437\u0432\u0443\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043e \u0432\u0442\u043e\u0440\u043e\u0435, \u0442\u043e \u043d\u0430\u0447\u043d\u0451\u0442\u0441\u044f \u0435\u0433\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u0437\u0430\u0442\u0435\u043c \u0442\u0440\u0435\u0442\u044c\u0435, \u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0444\u043e\u043d\u0438\u044f. \u0427\u0442\u043e\u0431\u044b \u044d\u0442\u043e\u0433\u043e \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u043e, \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u0435\u043c\u0430\u0444\u043e\u0440\u043e\u0432. \u041f\u0435\u0440\u0435\u0434 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0438 \u0436\u0434\u0451\u043c \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0441\u0435\u043c\u0430\u0444\u043e\u0440\u0430, \u0430 \u043f\u043e \u0435\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044e &#8212; \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u0435\u043c\u0430\u0444\u043e\u0440.<\/p>\n<pre><code class=\"python\">import threading   semaphore = threading.Semaphore(1)   def play_audio(self, audio):     \"\"\" Service method to play audio in monopoly mode using pydub      :param audio: AudioSegment needs to be played.     \"\"\"     playback.play(audio)     semaphore.release()  async def process_via_gtts(text):     \"\"\"     Converts text to speach using gtts text-to-speach method      :param text: Text needs to be converted to speach.     \"\"\"     temp_dir = tempfile.gettempdir()     tts = gTTS(text, lang=self.___lang)     raw_file = f\"{temp_dir}\/{str(uuid4())}.mp3\"     tts.save(raw_file)     audio = AudioSegment.from_file(raw_file, format=\"mp3\").speedup(self.___speedup)     os.remove(raw_file)     semaphore.acquire()     player_thread = threading.Thread(target=self.play_audio, args=(audio,))     player_thread.start()  def process_via_pytts(text):     \"\"\"     Converts text to speach using python-tts text-to-speach method      :param text: Text needs to be converted to speach.     \"\"\"     engine = self.___pytts     engine.setProperty(\"voice\", self.___voice)     engine.say(text)     engine.startLoop(False)      while engine.isBusy():         engine.iterate()         sleep(self.___frame)      engine.endLoop()     semaphore.release()  async def process(text):     \"\"\"     Converts text to speach using pre-defined model      :param text: Text needs to be converted to speach.     \"\"\"     if \"google\" in self.___method:         await self.__process_via_gtts(text)     else:         semaphore.acquire()         player_thread = threading.Thread(target=self.__process_via_pytts, args=(text,))         player_thread.start() <\/code><\/pre>\n<h2>\u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0417\u0430\u0447\u0435\u043c \u043e\u043d\u043e \u043d\u0443\u0436\u043d\u043e? \u0422\u0443\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0432\u043e\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439. \u041c\u043d\u0435 \u0431\u044b\u043b\u043e \u043b\u044e\u0431\u043e\u043f\u044b\u0442\u043d\u043e \u043f\u043e\u0438\u0437\u0443\u0447\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u043f\u0443\u0442\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 &#171;\u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043e\u0431\u0449\u0435\u043d\u0438\u044f&#187; \u0441 \u0447\u0430\u0442-\u0431\u043e\u0442\u0430\u043c\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u043e\u0439 \u0431\u043e\u0442 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c \u0430\u0441\u0441\u0438\u0441\u0442\u0435\u043d\u0442\u043e\u043c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u043f\u043e\u0434 \u0440\u0443\u043a\u043e\u0439 \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u0438 \u0432\u0435\u0434\u0443\u0449\u0438\u0439 \u0441\u0435\u0431\u044f \u0442\u0430\u043a, \u043a\u0430\u043a \u044f \u043e\u0436\u0438\u0434\u0430\u044e \u043e\u0442 \u043d\u0435\u0433\u043e. \u041d\u0443, \u0441\u043a\u0430\u0436\u0435\u043c, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043d\u0430\u043b\u0435\u0442\u0443 \u0443\u0437\u043d\u0430\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0433\u043e\u0434\u0443 \u0438\u043b\u0438 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u0443\u044e \u0434\u0435\u0432\u0443\u0448\u043a\u0443 \u043d\u0435\u043a\u0440\u043e\u043c\u0430\u043d\u0442\u0430 \u0432\u0435\u0440\u0445\u043e\u043c \u043d\u0430 \u0431\u0435\u043b\u043e\u0439 \u043b\u043e\u0448\u0430\u0434\u0438.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/065\/e6d\/4b3\/065e6d4b3a250adf627444512678c876.jpg\" alt=\"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0418\u0418\" title=\"\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0418\u0418\" width=\"1536\" height=\"1152\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/065\/e6d\/4b3\/065e6d4b3a250adf627444512678c876.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0421\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0418\u0418<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0451. \u0415\u0441\u043b\u0438 \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u0431\u044b\u043b \u0432\u0430\u043c \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u0442\u043e \u043d\u0435 \u0437\u0430\u0431\u0443\u0434\u044c\u0442\u0435 \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043b\u0430\u0439\u043a \u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0441\u0442\u0443, \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439, \u0430 \u0442\u0430\u043a \u0436\u0435, \u0435\u0441\u043b\u0438 \u0432\u043e\u043e\u0434\u0443\u0448\u0435\u0432\u0438\u0442\u0435\u0441\u044c &#8212; <a href=\"https:\/\/www.donationalerts.com\/r\/rocketsciencegeek\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u043c\u043e\u043d\u0435\u0442\u043a\u043e\u0439<\/a>. \u041e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/wwakabobik.github.io\/2023\/09\/ai_learning_to_hear_and_speak\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/759458\/\"> https:\/\/habr.com\/ru\/articles\/759458\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432\u043e\u0441\u043f\u0440\u0438\u044f\u0442\u0438\u044f \u0434\u043b\u044f \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0430. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u0444\u043e\u0440\u043c\u0430\u0442 \u0447\u0430\u0442\u0430 \u0441\u0430\u043c\u044b\u0439 \u043f\u043e\u043d\u044f\u0442\u043d\u044b\u0439 \u0438 \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0418\u0418. \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0435\u0440\u0435\u0437 \u0447\u0430\u0442 \u0433\u0440\u0435\u0435\u0442 \u043c\u043e\u044e \u0438\u043d\u0442\u0440\u043e\u0432\u0435\u0440\u0442\u0438\u0432\u043d\u0443\u044e \u0434\u0443\u0448\u0443, \u0432\u0437\u0440\u0430\u0449\u0435\u043d\u043d\u0443\u044e \u043d\u0430 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A4%D0%B8%D0%B4%D0%BE%D0%BD%D0%B5%D1%82\" rel=\"noopener noreferrer nofollow\">BBS&#8217;\u043a\u0430\u0445<\/a> \u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0445 \u043e <a href=\"http:\/\/lib.ru\/ANEKDOTY\/9600.txt\" rel=\"noopener noreferrer nofollow\">\u041d\u0430\u0448BOFH<\/a>. \u041d\u043e, \u0432\u0441\u0451 \u0436\u0435, \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u0442\u0430\u043c\u0438 \u0431\u043e\u043b\u0435\u0435 &#171;\u0447\u0435\u043b\u043e\u0432\u0435\u0447\u043d\u044b\u043c&#187;, \u043d\u0430\u0443\u0447\u0438\u0442\u044c \u0438\u0445 \u0441\u043b\u0443\u0448\u0430\u0442\u044c, \u0441\u043b\u044b\u0448\u0430\u0442\u044c \u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c? \u0412\u0441\u0451, \u043e \u0447\u0451\u043c \u0434\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c \u0432 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u0438\u043b\u043b\u0435\u0440-\u0444\u0438\u0447\u0435\u0439, \u0438 \u0434\u0430\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u0445, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u044b \u043a \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c\u0443 \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0443 (LLM). \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u0445 \u043d\u0430 <em>Python<\/em>, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0436\u0435\u043b\u0430\u044e\u0449\u0435\u0433\u043e.<\/p>\n<h2>openai.Audio.transcribe<\/h2>\n<p>\u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 ChatGPT \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e LLM \u0434\u0432\u0438\u0436\u043a\u0430. \u0415\u0441\u043b\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a \u0435\u0433\u043e <a href=\"https:\/\/platform.openai.com\/docs\/introduction\" rel=\"noopener noreferrer nofollow\">API<\/a>, \u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c <strong>whisper-1,<\/strong> \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0443\u044e \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u0437\u0430 \u0442\u0440\u0430\u043d\u0441\u043a\u0440\u0438\u043f\u0446\u0438\u044e \u0442\u0435\u043a\u0441\u0442\u0430. \u0412\u0441\u0451, \u0447\u0442\u043e \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0432\u0430\u0448 \u0433\u043e\u043b\u043e\u0441 \u0432 \u0442\u0435\u043a\u0441\u0442, \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 <strong>openai.Audio.atranscribe<\/strong>. \u0417\u0434\u0435\u0441\u044c \u0438 \u0434\u0430\u043b\u0435\u0435 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b.<\/p>\n<pre><code class=\"python\">    import openai       async def transcript(file, prompt=None, language=\"en\", response_format=\"text\"):         \"\"\"         Wrapper for the transcribe function. Returns only the content of the message.          :param file: Path with filename to transcript.         :param prompt: Previous prompt. Default is None.         :param language: Language on which audio is. Default is 'en'.         :param response_format: default response format, by default is 'text'.                                Possible values are: json, text, srt, verbose_json, or vtt.           :return: transcription (text, json, srt, verbose_json or vtt)         \"\"\"         kwargs = {}         if prompt is not None:             kwargs[\"prompt\"] = prompt         return await openai.Audio.atranscribe(             model=\"whisper-1\",             file=file,             language=language,             response_format=response_format,             temperature=1,             **kwargs,         )<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u0437\u0432\u0430\u0442\u044c \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0435\u0439 \u0444\u0430\u0439\u043b.<\/p>\n<pre><code class=\"python\">    with open(file_path, \"rb\") as f:         transcript = await transcript(file=f, language=\"en\")     response = await ask_chat(transcript)  # this method is for prompting LLM using pure string<\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0444\u0430\u0439\u043b &#8212; \u044d\u0442\u043e \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u043d\u043e \u0441\u0442\u043e\u0438\u0442 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0442\u044b \u043a\u0430\u0440\u0442\u0438\u043d\u044b \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c, \u0447\u0442\u043e \u0432\u044b, \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e, \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0433\u043e\u043b\u043e\u0441 \u043d\u0430\u043b\u0435\u0442\u0443?\u00a0<\/p>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 &#8212; \u044d\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>sounddevice<\/strong>. \u0422\u0430\u043a \u043a\u0430\u043a <strong>sounddevice<\/strong> \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <em>wav<\/em>, \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u0435\u0433\u043e \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u0432\u0441\u0451-\u0442\u0430\u043a\u0438 \u0441\u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 <em>mp3<\/em>, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <strong>pydab<\/strong>. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"python\">import os import tempfile import uuid  import sounddevice as sd import soundfile as sf from pydub import AudioSegment   def record_and_convert_audio(duration: int = 5, frequency_sample: int = 16000):     \"\"\"     Records audio for a specified duration and converts it to MP3 format.          This function records audio for a given duration (in seconds) with a specified frequency sample.     The audio is then saved as a temporary .wav file, converted to .mp3 format, and the .wav file is deleted.     The function returns the path to the .mp3 file.          :param duration: The duration of the audio recording in seconds. Default is 5 seconds.     :param frequency_sample: The frequency sample rate of the audio recording. Default is 16000 Hz.          :return: The path to the saved .mp3 file.     \"\"\"     print(f\"Listening beginning for {duration}s...\")     recording = sd.rec(int(duration * frequency_sample), samplerate=frequency_sample, channels=1)     sd.wait()  # Wait until recording is finished     print(\"Recording complete!\")     temp_dir = tempfile.gettempdir()     wave_file = f\"{temp_dir}\/{str(uuid.uuid4())}.wav\"     sf.write(wave_file, recording, frequency_sample)     print(f\"Temp audiofile saved: {wave_file}\")     audio = AudioSegment.from_wav(wave_file)     os.remove(wave_file)     mp3_file = f\"{temp_dir}\/{str(uuid.uuid4())}.mp3\"     audio.export(mp3_file, format=\"mp3\")     print(f\"Audio converted to MP3 and stored into {mp3_file}\")     return mp3_file<\/code><\/pre>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0443\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u0440\u043c\u0438\u0442\u044c \u043c\u043e\u0434\u0435\u043b\u0438. \u041d\u043e \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u0447\u0435\u043d\u044c \u0442\u043e\u043f\u043e\u0440\u043d\u044b\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442\u0441\u044f \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0432\u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u0432\u044b \u0434\u043e\u043b\u0433\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u0435 &#8212; \u043c\u0435\u043d\u044c\u0448\u0435, \u0447\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u0438 \u0432\u0430\u043c \u043f\u0440\u0438\u0434\u0451\u0442\u0441\u044f \u0436\u0434\u0430\u0442\u044c \u043e\u043a\u043e\u043d\u0447\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u0442 \u043a \u043e\u0431\u0440\u0435\u0437\u043a\u0435 \u0444\u0440\u0430\u0437\u044b. \u041e\u0431\u044b\u0447\u043d\u043e \u0441\u0430\u043c\u044b\u043c \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <em>push-to-talk<\/em>. \u041f\u043e\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442 \u043a\u043d\u043e\u043f\u043a\u0443, \u0438\u0434\u0451\u0442 \u0437\u0430\u043f\u0438\u0441\u044c. \u0422\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u044b \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043e\u043d\u043b\u0430\u0439\u043d \u0447\u0430\u0442\u044b. \u041d\u043e \u043c\u043d\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0432\u0441\u0451 \u0435\u0449\u0451 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e &#171;\u0447\u0435\u043b\u043e\u0432\u0435\u0447\u043d\u044b\u043c&#187; \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043d\u0435 \u0432\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u044e \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e \u0443\u0448\u0438 \u0418\u0418. \u041c\u043d\u0435, \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u043a\u043e\u043d\u0441\u043e\u043b\u0438, \u0431\u044b\u043b\u043e \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u0435\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u043a\u043d\u043e\u043f\u043e\u043a, \u0438, \u043f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0451\u0442\u0443, \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u044d\u0442\u0443 \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u0434\u0443: \u0442\u043e \u0435\u0441\u0442\u044c \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e, \u0438 \u0435\u0441\u043b\u0438 \u0432 \u0448\u0443\u043c\u0435 \u0437\u0430\u043c\u0435\u0447\u0435\u043d\u0430 \u0440\u0435\u0447\u044c, \u0442\u043e \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u0435\u0451. \u041d\u0443, \u043f\u043e\u0447\u0442\u0438 \u0442\u0430\u043a, \u043a\u0430\u043a \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <em>Google Assistant<\/em>, <em>Siri<\/em> \u0438 \u0443\u043c\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0430-\u043b\u044f \u0410\u043b\u0438\u0441\u0430 \u0432 \u0432\u0430\u0448\u0435\u043c \u0434\u043e\u043c\u0435. \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u043b\u044e\u0431\u043e\u0439 \u0437\u0432\u0443\u043a, \u0432\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0430\u0448\u0443 catch-\u0444\u0440\u0430\u0437\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u0437\u043d\u0430\u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u0439 (\u0432\u043d\u0430\u0447\u0430\u043b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438).<\/p>\n<pre><code class=\"python\">import re  pattern = r\"hellos*,?s*bunny\" if re.match(pattern, transcript, re.IGNORECASE):     prompt = re.sub(pattern, '', text, flags=re.IGNORECASE).lstrip()     response = await ask_chat(prompt)<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0436, \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043c\u043e\u0439 <strong>AudioRecorde<\/strong>r, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 <strong>pyaudio<\/strong>. \u041e\u043d \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u044c \u043c\u0438\u043a\u0440\u043e\u0444\u043e\u043d \u0438 \u0434\u0435\u0442\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0448\u0443\u043c (\u0440\u0435\u0447\u044c) \u043d\u0430 \u0444\u043e\u043d\u0435 \u0442\u0438\u0448\u0438\u043d\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A1%D1%80%D0%B5%D0%B4%D0%BD%D0%B5%D0%B5_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5\" rel=\"noopener noreferrer nofollow\">\u0441\u0440\u0435\u0434\u043d\u0435\u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u0435\u043d\u0438\u0435<\/a>. \u041f\u043e\u043b\u043d\u0430\u044f \u043f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c.<\/p>\n<details class=\"spoiler\">\n<summary>Hidden text<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">import math import os import struct import tempfile import time import uuid import wave  import pyaudio from pydub import AudioSegment   class AudioRecorder:     \"\"\"     The AudioRecorder class is for managing an instance of the audio recording and conversion process.      Parameters:     pyaudio_obj (PyAudio): Instance of PyAudio. Default is pyaudio.PyAudio().     threshold (int): The RMS threshold for starting the recording. Default is 15.     channels (int): The number of channels in the audio stream. Default is 1.     chunk (int): The number of frames per buffer. Default is 1024.     f_format (int): The format of the audio stream. Default is pyaudio.paInt16.     rate (int): The sample rate of the audio stream. Default is 16000 Hz.     sample_width (int): The sample width (in bytes) of the audio stream. Default is 2.     timeout_length (int): The length of the timeout for the recording (in seconds). Default is 2 seconds.     temp_dir (str): The directory for storing the temporary .wav and .mp3 files. Default is the system's temporary dir.     normalize (float): The normalization factor for the audio samples. Default is 1.0 \/ 32768.0.     pa_input (bool): Specifies whether the stream is an input stream. Default is True.     pa_output (bool): Specifies whether the stream is an output stream. Default is True.     \"\"\"      def __init__(         self,         pyaudio_obj=pyaudio.PyAudio(),         threshold=15,         channels=1,         chunk=1024,         f_format=pyaudio.paInt16,         rate=16000,         sample_width=2,         timeout_length=2,         temp_dir=tempfile.gettempdir(),         normalize=(1.0 \/ 32768.0),         pa_input=True,         pa_output=True,     ):         \"\"\"         General init.          This method initializes an instance of the AudioRecorder class with the specified parameters.         The default values are used for any parameters that are not provided.          :param pyaudio_obj: Instance of PyAudio. Default is pyaudio.PyAudio().         :param threshold: The RMS threshold for starting the recording. Default is 15.         :param channels: The number of channels in the audio stream. Default is 1.         :param chunk: The number of frames per buffer. Default is 1024.         :param f_format: The format of the audio stream. Default is pyaudio.paInt16.         :param rate: The sample rate of the audio stream. Default is 16000 Hz.         :param sample_width: The sample width (in bytes) of the audio stream. Default is 2.         :param timeout_length: The length of the timeout for the recording (in seconds). Default is 2 seconds.         :param temp_dir: The directory for storing the temporary .wav and .mp3 files. Default is temp dir.         :param normalize: The normalization factor for the audio samples. Default is 1.0 \/ 32768.0.         :param pa_input: Specifies whether the stream is an input stream. Default is True.         :param pa_output: Specifies whether the stream is an output stream. Default is True.         \"\"\"         self.___pyaudio = pyaudio_obj         self.___threshold = threshold         self.___channels = channels         self.___chunk = chunk         self.___format = f_format         self.___rate = rate         self.___sample_width = sample_width         self.___timeout_length = timeout_length         self.___temp_dir = temp_dir         self.___normalize = normalize         self.___input = pa_input         self.___output = pa_output         self.stream = self.init_stream(             f_format=self.___format,             channels=self.___channels,             rate=self.___rate,             pa_input=self.___input,             pa_output=self.___output,             frames_per_buffer=self.___chunk,         )      def init_stream(self, f_format, channels, rate, pa_input, pa_output, frames_per_buffer):         \"\"\"         Initializes an audio stream with the specified parameters.          This function uses PyAudio to open an audio stream with the given format, channels, rate, input, output,         and frames per buffer.          :param f_format: The format of the audio stream.         :param channels: The number of channels in the audio stream.         :param rate: The sample rate of the audio stream.         :param pa_input: Specifies whether the stream is an input stream. A true value<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-354242","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=354242"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/354242\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=354242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=354242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=354242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}