summaryrefslogtreecommitdiff
path: root/modules/video-audio-recording.el
Commit message (Collapse)AuthorAgeFilesLines
* fix(recording): create the selected recording directory, not its parentCraig Jennings13 days1-14/+20
| | | | | | The recording toggles took a directory from the prefix-arg prompt (or the default), then ran (file-name-directory location) before make-directory. For a path without a trailing slash that returns the parent, so make-directory created the parent and left the selected directory uncreated — ffmpeg then failed to write into it. Both toggles now route the destination through cj/recording--normalize-recording-dir, which expands and applies file-name-as-directory, then call make-directory on that normalized path. The selected directory itself is created (parents=t is a no-op when it already exists), including names with spaces. Tests cover trailing-slash normalization, idempotence, spaces, and relative-to-absolute expansion.
* fix(recording): scope wf-recorder stop signal to our own processCraig Jennings13 days1-4/+19
| | | | | | Stopping a Wayland recording ran pkill -INT wf-recorder, which signals every wf-recorder on the system — including an unrelated screen capture the user started outside Emacs. The stop path now scopes the producer-first interrupt to the wf-recorder child of our own recording shell via pkill -P <shell-pid>, in the new cj/recording--interrupt-child-wf-recorder helper. The producer-first ordering is unchanged: wf-recorder still gets SIGINT before the process-group signal so ffmpeg sees a clean EOF on pipe:0 and finalizes the MKV. The orphan-cleanup at recording start stays a broad by-name kill on purpose — those leftover recorders come from crashed sessions whose shells are already dead, so there is no live PID to scope to. Tests cover the scoped call, the nil-PID no-op, and that the bare system-wide form is never used.
* fix(recording): shell-quote device names and output paths in ffmpeg commandsCraig Jennings13 days1-19/+25
| | | | | | The X11 video path and the audio path interpolated the mic device, system device, and output filename straight into the shell command, so a device name or recording directory with a space (or other shell metacharacter) would break the command or mishandle the path. The Wayland video branch already quoted these; the other two did not. I wrapped all three in shell-quote-argument on both paths. To make the audio command testable, I extracted it into cj/recording--build-audio-command mirroring the existing cj/recording--build-video-command, then quoted there. Tests cover device names and filenames with spaces on both the X11 and audio builders.
* refactor(recording): extract select-from-labeled helper, flatten quick-setupCraig Jennings2026-04-051-33/+27
| | | | | | Extracted completing-read+cancel pattern into cj/recording--select-from-labeled. Reduces quick-setup nesting from 5 to 3 levels and eliminates duplicated completion table lambda.
* refactor(recording): extract video command builder from ffmpeg-record-videoCraig Jennings2026-04-051-42/+42
| | | | | Moved Wayland/X11 command string construction into cj/recording--build-video-command. Reduces ffmpeg-record-video from 70 to 25 lines, nesting from 4 to 2 levels.
* refactor(recording): extract shared test-device helper from ↵Craig Jennings2026-04-051-21/+16
| | | | | | | test-mic/test-monitor Both functions had identical record-5-seconds-and-playback logic. Extracted to cj/recording--test-device with device, prefix, and prompt-action parameters.
* refactor(recording): unify parse-pactl-sources/sinks-verbose into single ↵Craig Jennings2026-04-051-45/+12
| | | | | | | function Identical 31-line parser logic differed only in "Source #" vs "Sink #" header. Replaced with cj/recording--parse-pactl-verbose taking a record-type parameter.
* feat(recording): intuitive labels, show muted devices, add app namesCraig Jennings2026-02-261-49/+105
| | | | | | | | | | | | | Rework quick-setup device picker: - Labels: [in use], [ready], [available], [muted] instead of PulseAudio jargon (RUNNING/IDLE/SUSPENDED) - Muted devices now shown (previously hidden) so users can see all connected hardware and understand why a device is unsuitable - Sink step shows which apps are playing through each output: "JDS Labs Element IV [in use] (Firefox, Spotify)" - Prompt changed from "audio output to monitor" to "audio output to capture" to avoid PulseAudio monitor terminology confusion - Sort order: in use → ready → available → muted
* feat(recording): replace icons with text state labels in quick-setupCraig Jennings2026-02-261-75/+60
| | | | | | | | | | | | Replace hard-to-distinguish nerd font icons with clear text labels: Jabra SPEAK 510 Mono [active - running] Shure MV7+ Analog Stereo [active - idle] Ryzen HD Audio Controller [inactive - suspended] Both mic and sink steps use the same labeling. Devices sorted running → idle → suspended. Removed mic-active-p and sink-active-p helpers — state now comes directly from the verbose pactl parsers via get-available-mics/sinks which return (name description state).
* feat(recording): add mic indicators and fix misleading sink iconCraig Jennings2026-02-261-17/+42
| | | | | | | | | Mic step now shows 󰍬 with green/dim coloring to indicate which mics are actively in use (RUNNING state), with active mics sorted to top. Changed sink inactive icon from 󰖁 (slashed speaker, reads as "broken/muted") to 󰖀 (plain speaker, reads as "no streams right now"). Active sinks still show 󰕾.
* fix(recording): remove drift detection that overrides explicit sink choiceCraig Jennings2026-02-261-22/+14
| | | | | | | | | | | | Validation Check 2 (default sink drifted) would silently replace the user's explicit sink selection from quick-setup with the default sink's monitor on every recording start. Removed it — if the device still exists, trust the user's choice. The no-audio warning (Check 3) already catches wrong-sink scenarios. Also fix commentary: device selection does not persist across sessions (both vars are plain defvar), and update validation section to match the two remaining checks.
* feat(recording): show sinks with active audio indicators in quick-setupCraig Jennings2026-02-261-35/+123
| | | | | | | | | | Quick-setup (C-; r s) is now a two-step flow: pick a mic, then pick an audio output sink. Sinks display 󰕾/󰖁 icons with green/dim coloring to indicate which have active audio streams, with active sinks sorted to the top. The chosen sink's .monitor is set as the system audio device. This replaces the old auto-default-sink approach, letting users see where audio is actually going and pick the right sink in one command.
* fix(recording): replace blocking y-or-n-p with non-blocking warningCraig Jennings2026-02-261-9/+20
| | | | | | | | The no-audio warning was a y-or-n-p prompt that blocked recording start. This fires too often in legitimate scenarios (starting before a meeting connects, during silence). Replace with a message in the echo area and diagnostic steps logged silently to *Messages*. Also add pre-recording validation to the Commentary section.
* feat(recording): validate system audio device before recordingCraig Jennings2026-02-261-0/+81
| | | | | | | | | | Add pre-recording validation that catches stale or drifted system audio devices before they cause silent recordings. When the default audio output changes (Bluetooth reconnect, device switch) between setup and recording, the monitor device is auto-updated. Warns if no audio is currently playing through the monitored sink. Co-Authored-By: Craig Jennings <c@cjennings.net>
* fix(test): add missing testutil require for sanitize-org-body testsCraig Jennings2026-02-061-4/+4
|
* feat(recording): rewrite device setup, fix video stop, update modeline iconsCraig Jennings2026-02-061-206/+427
| | | | | | | | | | | | | | | Video stop fix: kill wf-recorder (producer) first on Wayland so ffmpeg gets clean EOF, then signal process group. Replaces sit-for with poll-based wait-for-exit. Fixes zero-byte output files. Device selection: rewrite quick setup to show all available mics with PulseAudio descriptions, auto-detect default sink monitor for system audio. Skip confirmation dialog, add Cancel option to mic list. Modeline: replace red dot emoji with nerd font icons (mic/camcorder). Rename quick-setup-for-calls to quick-setup, rebind C-; r s / C-; r S. 173 recording tests pass (was 165).
* fix(video-recording): kill orphan wf-recorder on WaylandCraig Jennings2026-02-031-1/+10
| | | | | | | | | | | On Wayland, video recording uses a shell pipeline: wf-recorder | ffmpeg. When stopping, SIGINT only reaches ffmpeg, leaving wf-recorder running as an orphan. This blocks subsequent recordings (0-byte files or no file). Fix: - On stop: explicitly pkill wf-recorder before interrupting ffmpeg - On start: kill any orphan wf-recorder from previous crashes - Increase finalization wait from 0.2s to 0.5s for proper cleanup
* fix(video-recording): use generic 'Built-in Audio' labelCraig Jennings2026-02-031-1/+1
| | | | | Renamed 'Built-in Laptop Audio' to 'Built-in Audio' since PCI audio devices are used on both laptops and desktops.
* fix(video-recording): correct wf-recorder flags for Wayland pipelineCraig Jennings2026-02-031-1/+1
| | | | | | | | | | | | | The wf-recorder command had several incorrect flags: - `--no-audio`: not a valid option (wf-recorder doesn't record audio by default) - `-c h264`: wrong encoder name, should be `libx264` - `-f matroska -o -`: `-o` is for selecting monitor, `-f` is for output file Fixed to use: `-y -c libx264 -m matroska -f /dev/stdout` - `-y`: auto-confirm overwrite (avoids prompt for /dev/stdout) - `-c libx264`: correct encoder name - `-m matroska`: set container format - `-f /dev/stdout`: output file to stdout for piping to ffmpeg
* fix(recording): add Wayland support using wf-recorderCraig Jennings2026-01-311-31/+66
| | | | | | x11grab produces black video on Wayland. Now detects session type and uses wf-recorder for screen capture on Wayland, falling back to x11grab on X11. wf-recorder pipes H264 to ffmpeg for audio mixing.
* fix(tests): Move cj/log-silently to system-lib.el, fix all test failuresCraig Jennings2025-11-151-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | Consolidated cj/log-silently function to system-lib.el as the canonical location for low-level utility functions. This fixes 4 failing tests in video-audio-recording that couldn't find the function. Changes: - Move cj/log-silently to system-lib.el (from system-utils.el) - Remove duplicate definition from org-agenda-config-debug.el - Remove duplicate definition from system-utils.el - Add (require 'system-lib) to all modules using cj/log-silently: - video-audio-recording.el - org-agenda-config-debug.el - media-utils.el (also removed declare-function) - elfeed-config.el (replaced system-utils with system-lib) - wrap-up.el Test Results: - Before: 112/113 passing (4 video-audio-recording tests failing) - After: 113/113 passing ✓ All tests now pass with zero failures. Fixes TODO #809-895 (move cj/log-silently to system-lib.el)
* fix(recording): Fix phone call audio capture with amix filterCraig Jennings2025-11-141-10/+60
| | | | | | | | | | | | | | | | Phone calls were not capturing the remote person's voice due to severe volume loss (44 dB) when using the amerge+pan FFmpeg filter combination. Changes: - Replace amerge+pan with amix filter (provides 44 dB volume improvement) - Increase default system volume from 0.5 to 2.0 for better capture levels - Add diagnostic tool to show active audio playback (C-; r w) - Add integration test with real voice recording - Fix batch mode compatibility for test execution The amix filter properly mixes microphone and system monitor inputs without the massive volume loss that amerge+pan caused. Verified with automated integration test showing perfect transcription of test audio.
* a/v recording: fix setup, add test functionality and indicatorlkgCraig Jennings2025-11-111-51/+208
| | | | | | | | | Integrates a modeline indicator to display active recording status in Emacs. The indicator shows "🔴Audio", "🔴Video", or "🔴A+V" based on the active recording processes. Includes functions for starting and stopping audio/video recordings, with sentinel processes ensuring timely updates to the modeline. Also adds extensive integration tests to validate modeline synchronization.
* feat: Add AssemblyAI transcription backend with speaker diarizationCraig Jennings2025-11-061-6/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Integrated AssemblyAI as the third transcription backend alongside OpenAI API and local-whisper, now set as the default due to superior speaker diarization capabilities (up to 50 speakers). New Features: - AssemblyAI backend with automatic speaker labeling - Backend switching UI via C-; T b (completing-read interface) - Universal speech model supporting 99 languages - API key management through auth-source/authinfo.gpg Implementation: - Created scripts/assemblyai-transcribe (upload → poll → format workflow) - Updated transcription-config.el with multi-backend support - Added cj/--get-assemblyai-api-key for secure credential retrieval - Refactored process environment handling from if to pcase - Added cj/transcription-switch-backend interactive command Testing: - Created test-transcription-config--transcription-script-path.el - 5 unit tests covering all 3 backends (100% passing) - Followed quality-engineer.org guidelines (test pure functions only) - Investigated 18 test failures: documented cleanup in todo.org Files Modified: - modules/transcription-config.el - Multi-backend support and UI - scripts/assemblyai-transcribe - NEW: AssemblyAI integration script - tests/test-transcription-config--transcription-script-path.el - NEW - todo.org - Added test cleanup task (Method 3, priority C) - docs/NOTES.org - Comprehensive session notes added Successfully tested with 33KB and 4.1MB audio files (3s and 9s processing).
* style: Fix checkdoc warnings in video-audio-recording.elCraig Jennings2025-11-031-6/+6
| | | | | | | | | | | | | Resolved 6 checkdoc linting warnings: - Added double spaces after periods in docstrings (Emacs convention) - Changed "calls" to "call" in docstring (imperative form) All linting checks now pass: - checkdoc: ✓ No warnings - make lint: ✓ Passes - All 83 tests: ✓ Still passing Also updated docs/sessions/refactor.org to be more generic/reusable.
* test: Add comprehensive test suite for video-audio-recording moduleCraig Jennings2025-11-031-5/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Added 83 test cases across 9 test files with 100% pass rate, covering device detection, parsing, grouping, and complete workflow integration. ## What Was Done ### Refactoring for Testability - Extracted `cj/recording--parse-pactl-output` from `cj/recording-parse-sources` - Separated parsing logic from shell command execution - Enables testing with fixture data instead of live system calls ### Test Fixtures Created - `pactl-output-normal.txt` - All device types (built-in, USB, Bluetooth) - `pactl-output-empty.txt` - Empty output - `pactl-output-single.txt` - Single device - `pactl-output-monitors-only.txt` - Only monitor devices - `pactl-output-inputs-only.txt` - Only input devices - `pactl-output-malformed.txt` - Invalid/malformed output ### Unit Tests (8 files, 78 test cases) 1. **test-video-audio-recording-friendly-state.el** (10 tests) - State name conversion: SUSPENDED→Ready, RUNNING→Active 2. **test-video-audio-recording-parse-pactl-output.el** (14 tests) - Parse raw pactl output into structured data - Handle empty, malformed, and mixed valid/invalid input 3. **test-video-audio-recording-parse-sources.el** (6 tests) - Shell command wrapper testing with mocked output 4. **test-video-audio-recording-detect-mic-device.el** (13 tests) - Documents bugs: Returns ID numbers instead of device names - Doesn't filter monitors (legacy function, not actively used) 5. **test-video-audio-recording-detect-system-device.el** (13 tests) - Works correctly: Returns full device names - Tests monitor detection with various device types 6. **test-video-audio-recording-group-devices-by-hardware.el** (12 tests) - CRITICAL: Bluetooth MAC address normalization (colons vs underscores) - Device pairing logic (mic + monitor from same hardware) - Friendly name assignment - Filters incomplete devices 7. **test-video-audio-recording-check-ffmpeg.el** (3 tests) - ffmpeg availability detection 8. **test-video-audio-recording-get-devices.el** (7 tests) - Auto-detection fallback logic - Error handling for incomplete detection ### Integration Tests (1 file, 5 test cases) 9. **test-integration-recording-device-workflow.el** (5 tests) - Complete workflow: parse → group → friendly names - Bluetooth MAC normalization end-to-end - Incomplete device filtering across components - Malformed data graceful handling ## Key Testing Insights ### Bugs Documented - `cj/recording-detect-mic-device` has bugs (returns IDs, doesn't filter monitors) - These functions appear to be legacy code not used by main workflow - Tests document current behavior to catch regressions if fixed ### Critical Features Validated - **Bluetooth MAC normalization**: Input uses colons (00:1B:66:C0:91:6D), output uses underscores (00_1B_66_C0_91_6D), grouping normalizes correctly - **Device pairing**: Only devices with BOTH mic and monitor are included - **Friendly names**: USB/PCI/Bluetooth patterns correctly identified ### Test Coverage - Normal cases: Valid inputs, typical workflows - Boundary cases: Empty, single device, incomplete pairs - Error cases: Malformed input, missing devices, partial detection ## Test Execution All tests pass: 9/9 files, 83/83 test cases (100% pass rate) ```bash make test-file FILE=test-video-audio-recording-*.el # All pass individually # Integration test also passes make test-file FILE=test-integration-recording-device-workflow.el ```
* feat: Add quick setup for call recording with automatic device pairingCraig Jennings2025-11-031-1/+71
| | | | | | | | | | | | | | | | Users needed a faster way to configure audio for call recording. This adds cj/recording-quick-setup-for-calls which automatically groups audio devices by hardware and lets users pick one device for both mic and monitor. Key improvements: - Groups devices by hardware (USB, built-in, Bluetooth) - Normalizes Bluetooth MAC addresses (handles colon/underscore formats) - Shows friendly device names (e.g., "Jabra SPEAK 510 USB") - Automatically pairs mic + monitor from same device - Bound to C-; r c for quick access Perfect for recording video calls where you need to capture both your voice and the remote person's voice through the same audio device.
* ux: Use friendlier labels for device states in recording moduleCraig Jennings2025-11-031-4/+16
| | | | | | | | | | | | | Replace technical state names with user-friendly labels: - "SUSPENDED" → "Ready" (device available, will activate on use) - "RUNNING" → "Active" (device currently in use) - "IDLE" → "Ready" Add explanatory note in device list buffer explaining that "Ready" devices are normal and will activate automatically when recording starts. Prevents user confusion - "SUSPENDED" sounds like something is wrong when it's actually the normal idle state.
* feat: Add device selection and diagnostics to recording moduleCraig Jennings2025-11-031-3/+80
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Add interactive device selection to fix recording with multiple audio devices. New features: - cj/recording-list-devices (C-; r d) - Show all available audio sources - cj/recording-select-devices (C-; r s) - Interactively select mic/monitor - cj/recording-parse-sources - Parse pactl output into structured data - Enhanced cj/recording-get-devices with graceful fallback to manual selection Improvements: - Works with PulseAudio and PipeWire - Supports USB devices (Jabra SPEAK 510) - Supports Bluetooth devices - Supports built-in laptop audio - Shows device state (RUNNING, SUSPENDED) during selection - Better error messages with actionable suggestions - Device selection persists across recordings Fixes recording breakage when plugging in external audio interfaces. Addresses Method 1 (Make Using Emacs Frictionless) from V2MOM. Closes #[#B] Fix video/audio recording module sub-tasks: - Add diagnostic command - Add device selection UI - Improve error messages - Make device detection more flexible
* feat:which-key: Add descriptive labels for custom keymapsCraig Jennings2025-10-271-0/+9
| | | | | | | | | | | | Enhance which-key integration by providing detailed descriptions for new key bindings across multiple modules. This improves the usability of custom keymaps by clarifying the purpose of each keybinding, making it easier for users to navigate and understand different menus and options available within the configuration. This update ensures that all custom keymaps now display a descriptive label in the which-key popup to explain their functionality, aiding users in identifying keymap purposes promptly.
* refactor:video-audio-recording: remove unused autoload cookiesCraig Jennings2025-10-251-6/+1
| | | | | | Remove unnecessary `;;;###autoload` comments from function definitions. This cleanup clarifies the code and has no functional impact as these autoload cookies were not utilized.
* refactor:recording:: improve ffmpeg-based device detection + perfCraig Jennings2025-10-201-49/+101
| | | | | | | | | - Simplified variable declarations by using defvar instead of defcustom. - Added functions to auto-detect audio devices using PulseAudio - Enhanced ffmpeg command construction to include detected device names and optimized process start and stop messages. - Adjusted process interruption timing for better file finalization. - Autoload settings and key bindings have also been restructured.
* changing repositoriesCraig Jennings2025-10-121-0/+184