<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotemacs/tests/test-transcription-status-and-commands.el, branch main</title>
<subtitle>My Emacs configuration
</subtitle>
<id>https://git.cjennings.net/dotemacs/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/dotemacs/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/'/>
<updated>2026-05-14T19:09:16+00:00</updated>
<entry>
<title>feat(transcription): extend dired T to transcribe videos via ffmpeg, with tests</title>
<updated>2026-05-14T19:09:16+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-14T19:09:16+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=4a7529393ebbbc225939f21be783ec624d0a8168'/>
<id>urn:sha1:4a7529393ebbbc225939f21be783ec624d0a8168</id>
<content type='text'>
Pressing `T' in dired/dirvish on an audio file already transcribed
it; on a video file it bounced with "Not an audio file".  Real
recordings ship as .mp4 / .mkv at least as often as raw .m4a, so
the one-key flow ended at the wrong place.

Pipeline now:
- audio path -&gt; direct into `cj/--start-transcription-process'
  (unchanged).
- video path -&gt; async ffmpeg extracts the audio track to a temp
  .mp3 under `temporary-file-directory' (libmp3lame, VBR q:a 4,
  ~165kbps -- right size for speech, accepted by every backend),
  then transcribes that file with the temp marked for cleanup
  after the transcription sentinel fires.

Surface changes:
- `cj/video-file-extensions' added to user-constants.el (mp4, mkv,
  mov, webm, avi, m4v, wmv, flv, mpg, mpeg, 3gp, ogv).
- New predicates `cj/--video-file-p' / `cj/--media-file-p'.
- New `cj/--extract-audio-from-video' (async ffmpeg with success
  callback; surfaces `cj/--notify' on failure; user-errors if
  ffmpeg isn't on PATH).
- `cj/--start-transcription-process' gains optional `cleanup-file'.
  Sentinel deletes it after the existing logic runs.  Backwards
  compatible -- the audio flow doesn't pass it.
- `cj/transcribe-audio' renamed to `cj/transcribe-media' (dispatcher
  on audio vs video).  `cj/transcribe-audio-at-point' renamed to
  `cj/transcribe-media-at-point'.  Both old names kept as
  `defalias' so M-x history and any external references still work.
- `T' in dired-mode-map + dirvish-mode-map points at
  `cj/transcribe-media-at-point'.
- Module commentary USAGE block updated.

15 new ERT tests in `tests/test-transcription-video.el' cover the
predicates (happy/boundary/error), ffmpeg invocation (correct args
+ missing-ffmpeg path), the dispatcher (audio direct, video via
extraction, non-media rejected), the aliases, and the T binding.
One existing test in `test-transcription-status-and-commands.el'
updated to stub the new delegate name.

Verified locally that ffmpeg is on PATH with libmp3lame, and that
the exact arg list my code uses produces a valid MP3 from a
synthetic test video.
</content>
</entry>
<entry>
<title>test(transcription-config): cover status helpers + interactive commands</title>
<updated>2026-05-14T06:03:30+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-14T06:03:30+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/dotemacs/commit/?id=902693e9ea8ccf56d24a977d3d407f585c6cf046'/>
<id>urn:sha1:902693e9ea8ccf56d24a977d3d407f585c6cf046</id>
<content type='text'>
Sibling tests cover the audio-file predicate, path/duration helpers, log cleanup, sentinel helpers, and the process-environment builder. The gap was the running-list helpers and the interactive commands. 15 new tests cover:

- `cj/--running-transcriptions`: filters by `running` status, handles empty list.
- `cj/--cleanup-completed-transcriptions`: prunes the list down to running entries only.
- `cj/--count-active-transcriptions`: counts running, zero when empty.
- `cj/--transcription-modeline-string`: nil when idle, includes the active count when busy.
- `cj/transcriptions-buffer`: renders the empty-state message or per-entry rows.
- `cj/transcription-kill`: errors with no entries, calls `kill-process` on a live one.
- `cj/transcription-switch-backend`: completing-read picks the new backend, var + message updated.
- `cj/transcribe-audio-at-point`: errors outside dired / when no file at point, delegates otherwise.
</content>
</entry>
</feed>
