バッファ内のテキストをAIに喋らせる
最近では、難しい英単語のより正確な発音を知りたいというのもあります。まあ、ブラウザ内で検索すればGoogle先生が即座にその願いを叶えてくれますが、バッファ内で完結するのがEmacserの矜持というものです。はい。
AIブーム前夜まではローカルに用意したエンジンに喋ってもらっていました。日本語なら OpenJTalk に、英語なら Festival に。
しかし今や、音声合成の技術の発達とともに、AIの力で行われる圧倒的な構文解釈能力をベースにして驚くほどに人間に近い発話が可能になりました。なので、API経由でリージョン内のテキストをChatGPTに喋らせるコードを書きました。
Elisp Code for Text to Speech
(defun tts-openai-request (api-key input action)
"Return audio file content from OpenAI API and save it to OUTPUT-FILE or play it.
INPUT is the text string sent to the API.
RESPONSE-FORMAT is the format of the audio file, defaults to 'mp3'.
ACTION is either 'save or 'play, determining what to do with the response."
(let* ((auth-value (format "Bearer %s" api-key))
(model "tts-1")
(voice "nova")
(speed nil)
(response-format "opus")
(url "https://api.openai.com/v1/audio/speech")
(data (json-encode `(("model" . ,model)
("input" . ,input)
("voice" . ,voice)
,@(when response-format `(("response_format" . ,response-format)))
,@(when speed `(("speed" . ,speed)))))))
(request
url
:type "POST"
:data data
:headers `(("Authorization" . ,auth-value) ("Content-Type" . "application/json"))
:parser 'buffer-string
:success (cl-function
(lambda (&key data &allow-other-keys)
(let ((coding-system-for-write 'binary)
(speech-file (make-temp-file "tts-" nil ".opus")))
(with-temp-file speech-file
(insert data))
(when action (funcall action speech-file)))))
:error (cl-function
(lambda (&key error-thrown &allow-other-keys)
(message "Error: %S" error-thrown))))))
はい。書き方を見ればおわかりのとおり、ちゃっかりパッケージ化を目論んだ書き方になってますね。もしご所望の方がおられましたらご一報ください。がんばってみます。