SouthFox's Garden

Search IconA magnifying glass icon. 搜索

种植日期:

上次照料:

2026-03-23

全文翻译

(defun my/translate-buffer-immersive (current-pos &optional t-buffer stop)
  (interactive (list (point-min)))
  (with-current-buffer (current-buffer)
    (save-excursion
      (goto-char current-pos)
      (let ((bounds (bounds-of-thing-at-point 'paragraph))
            (api-url "http://localhost:8989/translate")
            (cb-buffer (or t-buffer (current-buffer))))
        (while (not bounds)
          (forward-line)
          (if (equal (point) (point-max))
              (setq bounds (cons 0 (point-max)))
            (setq bounds (bounds-of-thing-at-point 'paragraph))))
        (if (and (not stop) (>= (cdr bounds) (point-max)))
            (my/translate-buffer-immersive current-pos cb-buffer t)
          (let* ((start (car bounds))
                 (end (cdr bounds))
                 (text (buffer-substring-no-properties start end))
                 (clean-text (string-trim text)))
            (request api-url
              :type "POST"
              :data (json-encode `((from . "auto")
                                   (to . "zh-Hans")
                                   (text . ,text)))
              :headers '(("Content-Type" . "application/json; charset=utf-8"))
              :parser 'json-read
              :success (cl-function
                        (lambda (&key data &allow-other-keys)
                          (let ((translation (cdr (assoc 'result data))))
                            (with-current-buffer cb-buffer
                              (remove-overlays start end 'type 'translation)
                              (let ((ov (make-overlay start end)))
                                (overlay-put ov 'type 'translation)
                                (overlay-put ov 'evaporate t)
                                (overlay-put ov 'after-string
                                             (propertize translation
                                                         'face '(:inherit shadow :height 0.9))))
                              (unless stop
                                (my/translate-buffer-immersive (1+ end) cb-buffer))))))
              :error (cl-function
                      (lambda (&key error-thrown &allow-other-keys)
                        (message "Error: %S" error-thrown))))))))))
(defun my/piper-speak-buffer ()
  (interactive)
  (let* ((process-name "piper-mpv-full")
         (old-proc (get-process process-name))
         (text (string-trim (buffer-substring-no-properties (point-min) (point-max))))
         (api-url "http://localhost:5000")
         (temp-file (make-temp-file "piper_full_" nil ".wav")))
    (when old-proc
      (delete-process old-proc))
    (if (string-empty-p text)
        (message "Buffer empty")
      (request
        api-url
        :type "POST"
        :data (json-encode `((text . ,text)
                             ;; (voice . "de_DE-thorsten-medium")
                             ))
        :headers '(("Content-Type" . "application/json"))
        :parser 'buffer-string
        :encoding 'binary
        :success (cl-function
                  (lambda (&key data &allow-other-keys)
                    (let ((temp-file (make-temp-file "piper_full_" nil ".wav"))
                          (coding-system-for-write 'no-conversion))
                      (with-temp-buffer
                        (toggle-enable-multibyte-characters)
                        (set-buffer-file-coding-system 'raw-text)
                        (insert data)
                        (write-region nil nil temp-file))
                      (let ((proc (start-process process-name nil "mpv" "--no-video" temp-file)))
                        (message "Play!")
                        (set-process-sentinel
                         proc
                         (lambda (p e)
                           (when (string-match-p "\\(finished\\|exited\\|killed\\|signal\\)" e)
                             (when (file-exists-p temp-file)
                               (delete-file temp-file))
                             (message "Stop Play"))))))))
        :error (cl-function
                (lambda (&key error-thrown &allow-other-keys)
                  (message "Error: %S" error-thrown)))))))

emacs 里实践 外语学习 的一种方式。