From 3d9a650d9726c0d6091ff4d9fc7d98eba4819587 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 25 Jun 2026 14:03:17 -0400 Subject: fix(transcription): land video transcripts beside the source, not in /tmp The video flow extracts audio to a temp .mp3 in /tmp, then derived the .txt/.log from that temp path, so transcripts landed in /tmp and died on reboot, contradicting the "alongside the source" docstring. Thread the source video through cj/--start-transcription-process as an optional output base so the outputs derive from it (talk.mp4 -> talk.txt beside the video). Audio is unchanged. New regression test pins the output base to the source video. --- modules/transcription-config.el | 14 ++++++++++---- tests/test-transcription-video.el | 22 ++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/modules/transcription-config.el b/modules/transcription-config.el index 566cea499..e00306d1e 100644 --- a/modules/transcription-config.el +++ b/modules/transcription-config.el @@ -173,13 +173,17 @@ TITLE and MESSAGE are strings. URGENCY is normal or critical." :body message :urgency (or urgency 'normal)))) -(defun cj/--start-transcription-process (audio-file &optional cleanup-file) +(defun cj/--start-transcription-process (audio-file &optional cleanup-file output-base) "Start async transcription process for AUDIO-FILE. Returns the process object. When CLEANUP-FILE is non-nil, delete that path once the transcription sentinel fires (success or failure). Used by the video flow to drop -the temp audio file produced by ffmpeg after transcription completes." +the temp audio file produced by ffmpeg after transcription completes. + +OUTPUT-BASE, when non-nil, is the path the .txt/.log outputs derive from +instead of AUDIO-FILE. The video flow passes the original video so the +transcript lands alongside the source, not next to the temp /tmp audio." (unless (file-exists-p audio-file) (user-error "Audio file does not exist: %s" audio-file)) @@ -187,7 +191,7 @@ the temp audio file produced by ffmpeg after transcription completes." (user-error "Not an audio file: %s" audio-file)) (let* ((script (cj/--transcription-script-path)) - (outputs (cj/--transcription-output-files audio-file)) + (outputs (cj/--transcription-output-files (or output-base audio-file))) (txt-file (car outputs)) (log-file (cdr outputs)) (buffer-name (format " *transcribe-%s*" (file-name-nondirectory audio-file))) @@ -371,7 +375,9 @@ FILE.log with process logs. Uses the backend in (cj/--extract-audio-from-video path extracted (lambda () - (cj/--start-transcription-process extracted extracted)))))))) + ;; Pass the source video as the output base so the .txt/.log land + ;; alongside it, not next to the temp /tmp audio. + (cj/--start-transcription-process extracted extracted path)))))))) ;;;###autoload (defun cj/transcribe-media-at-point () diff --git a/tests/test-transcription-video.el b/tests/test-transcription-video.el index 8327fa326..aa8383d12 100644 --- a/tests/test-transcription-video.el +++ b/tests/test-transcription-video.el @@ -128,6 +128,28 @@ goes through `cj/--start-transcription-process' with a cleanup hint." ;; deleted after transcription completes). (should (equal (nth 1 extract-args) (cadr worker-call))))) +(ert-deftest test-tx-transcribe-media-video-output-base-is-the-source () + "Regression: a video's transcript derives from the VIDEO path (alongside the +source), not the temp /tmp audio. The worker gets the video as its output base +\(third arg), so cj/--transcription-output-files lands talk.mp4 -> talk.txt +beside the video instead of in /tmp." + (let* ((tmp (make-temp-file "cj-tx-vid-" nil ".mp4")) + worker-call) + (unwind-protect + (cl-letf (((symbol-function 'cj/--extract-audio-from-video) + (lambda (_vid _out cb) (funcall cb))) + ((symbol-function 'cj/--start-transcription-process) + (lambda (file &rest rest) + (setq worker-call (cons file rest)) + 'fake-proc))) + (cj/transcribe-media tmp)) + (delete-file tmp)) + ;; the output base (third arg) is the source video, not the temp audio + (should (equal (nth 2 worker-call) tmp)) + ;; so the derived transcript sits beside the video, not in /tmp + (should (equal (car (cj/--transcription-output-files (nth 2 worker-call))) + (concat (file-name-sans-extension tmp) ".txt"))))) + (ert-deftest test-tx-transcribe-media-rejects-non-media () "Error: non-media paths get rejected up front." (should-error (cj/transcribe-media "/notes/readme.txt") :type 'user-error)) -- cgit v1.2.3