summaryrefslogtreecommitdiff
path: root/modules/video-audio-recording.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/video-audio-recording.el')
-rw-r--r--modules/video-audio-recording.el150
1 files changed, 101 insertions, 49 deletions
diff --git a/modules/video-audio-recording.el b/modules/video-audio-recording.el
index e2238949..711e903c 100644
--- a/modules/video-audio-recording.el
+++ b/modules/video-audio-recording.el
@@ -20,25 +20,26 @@
;;
;;; Code:
-(require 'user-constants)
+;; Forward declarations
+(eval-when-compile (defvar video-recordings-dir))
+(eval-when-compile (defvar audio-recordings-dir))
+(defvar cj/custom-keymap)
-(defgroup cj-recording nil
- "Settings for video and audio recording."
- :group 'multimedia)
-
-(defcustom cj/recording-mic-boost 2.0
+(defvar cj/recording-mic-boost 2.0
"Volume multiplier for microphone in recordings.
+1.0 = normal volume, 2.0 = double volume (+6dB), 0.5 = half volume (-6dB).")
-1.0 = normal volume, 2.0 = double volume (+6dB), 0.5 = half volume (-6dB)."
- :type 'number
- :group 'cj-recording)
-
-(defcustom cj/recording-system-volume 0.5
+(defvar cj/recording-system-volume 0.5
"Volume multiplier for system audio in recordings.
+1.0 = normal volume, 2.0 = double volume (+6dB), 0.5 = half volume (-6dB).")
+
+(defvar cj/recording-mic-device nil
+ "PulseAudio device name for microphone input.
+If nil, will auto-detect on first use.")
-1.0 = normal volume, 2.0 = double volume (+6dB), 0.5 = half volume (-6dB)."
- :type 'number
- :group 'cj-recording)
+(defvar cj/recording-system-device nil
+ "PulseAudio device name for system audio monitor.
+If nil, will auto-detect on first use.")
(defvar cj/video-recording-ffmpeg-process nil
"Variable to store the process of the ffmpeg video recording.")
@@ -46,11 +47,48 @@
(defvar cj/audio-recording-ffmpeg-process nil
"Variable to store the process of the ffmpeg audio recording.")
+(defun cj/recording-check-ffmpeg ()
+ "Check if ffmpeg is available.
+Return t if found, nil otherwise."
+ (unless (executable-find "ffmpeg")
+ (user-error "Ffmpeg not found. Install with: sudo pacman -S ffmpeg")
+ nil)
+ t)
+
+(defun cj/recording-detect-mic-device ()
+ "Auto-detect PulseAudio microphone input device.
+Returns device name or nil if not found."
+ (let ((output (shell-command-to-string "pactl list sources short 2>/dev/null")))
+ (when (string-match "\\([^\t\n]+\\).*analog.*stereo" output)
+ (match-string 1 output))))
+
+(defun cj/recording-detect-system-device ()
+ "Auto-detect PulseAudio system audio monitor device.
+Returns device name or nil if not found."
+ (let ((output (shell-command-to-string "pactl list sources short 2>/dev/null")))
+ (when (string-match "\\([^\t\n]+\\.monitor\\)" output)
+ (match-string 1 output))))
+
+(defun cj/recording-get-devices ()
+ "Get or auto-detect audio devices.
+Returns (mic-device . system-device) or nil on error."
+ ;; Auto-detect if not already set
+ (unless cj/recording-mic-device
+ (setq cj/recording-mic-device (cj/recording-detect-mic-device)))
+ (unless cj/recording-system-device
+ (setq cj/recording-system-device (cj/recording-detect-system-device)))
+
+ ;; Validate devices
+ (unless (and cj/recording-mic-device cj/recording-system-device)
+ (user-error "Could not detect audio devices. Set cj/recording-mic-device and cj/recording-system-device manually"))
+
+ (cons cj/recording-mic-device cj/recording-system-device))
+
+;;;###autoload
(defun cj/video-recording-start (arg)
- "Starts the ffmpeg video recording.
-
-If called with a prefix arg C-u, choose the location on where to save the
-recording, otherwise use the default location in =video-recordings-dir'."
+ "Start the ffmpeg video recording.
+With prefix ARG, prompt for recording location.
+Otherwise use the default location in `video-recordings-dir'."
(interactive "P")
(let* ((location (if arg
(read-directory-name "Enter recording location: ")
@@ -60,15 +98,15 @@ recording, otherwise use the default location in =video-recordings-dir'."
(make-directory directory t))
(cj/ffmpeg-record-video location)))
+;;;###autoload
(defun cj/audio-recording-start (arg)
- "Starts the ffmpeg audio recording.
-
-If called with a prefix arg C-u, choose the location on where to save the
-recording, otherwise use the default location in =video-recordings-dir'."
+ "Start the ffmpeg audio recording.
+With prefix ARG, prompt for recording location.
+Otherwise use the default location in `audio-recordings-dir'."
(interactive "P")
(let* ((location (if arg
(read-directory-name "Enter recording location: ")
- video-recordings-dir))
+ audio-recordings-dir))
(directory (file-name-directory location)))
(unless (file-directory-p directory)
(make-directory directory t))
@@ -76,21 +114,25 @@ recording, otherwise use the default location in =video-recordings-dir'."
(defun cj/ffmpeg-record-video (directory)
"Start an ffmpeg video recording. Save output to DIRECTORY."
+ (cj/recording-check-ffmpeg)
(unless cj/video-recording-ffmpeg-process
- (let* ((location (expand-file-name directory))
+ (let* ((devices (cj/recording-get-devices))
+ (mic-device (car devices))
+ (system-device (cdr devices))
+ (location (expand-file-name directory))
(name (format-time-string "%Y-%m-%d-%H-%M-%S"))
(filename (expand-file-name (concat name ".mkv") location))
(ffmpeg-command
(format (concat "ffmpeg -framerate 30 -f x11grab -i :0.0+ "
- "-f pulse -i "
- "alsa_input.pci-0000_00_1b.0.analog-stereo "
+ "-f pulse -i %s "
"-ac 1 "
- "-f pulse -i "
- "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor "
+ "-f pulse -i %s "
"-ac 2 "
"-filter_complex \"[1:a]volume=%.1f[mic];[2:a]volume=%.1f[sys];[mic][sys]amerge=inputs=2[out]\" "
"-map 0:v -map \"[out]\" "
"%s")
+ mic-device
+ system-device
cj/recording-mic-boost
cj/recording-system-volume
filename)))
@@ -100,27 +142,31 @@ recording, otherwise use the default location in =video-recordings-dir'."
"*ffmpeg-video-recording*"
ffmpeg-command))
(set-process-query-on-exit-flag cj/video-recording-ffmpeg-process nil)
- (message "Started video recording process (mic boost: %.1fx, system volume: %.1fx)."
- cj/recording-mic-boost cj/recording-system-volume))))
+ (message "Started video recording to %s (mic: %.1fx, system: %.1fx)."
+ filename cj/recording-mic-boost cj/recording-system-volume))))
(defun cj/ffmpeg-record-audio (directory)
"Start an ffmpeg audio recording. Save output to DIRECTORY."
+ (cj/recording-check-ffmpeg)
(unless cj/audio-recording-ffmpeg-process
- (let* ((location (expand-file-name directory))
+ (let* ((devices (cj/recording-get-devices))
+ (mic-device (car devices))
+ (system-device (cdr devices))
+ (location (expand-file-name directory))
(name (format-time-string "%Y-%m-%d-%H-%M-%S"))
(filename (expand-file-name (concat name ".opus") location))
(ffmpeg-command
(format (concat "ffmpeg "
- "-f pulse -i "
- "alsa_input.pci-0000_00_1b.0.analog-stereo "
+ "-f pulse -i %s "
"-ac 1 "
- "-f pulse -i "
- "alsa_output.pci-0000_00_1b.0.analog-stereo.monitor "
+ "-f pulse -i %s "
"-ac 2 "
"-filter_complex \"[0:a]volume=%.1f[mic];[1:a]volume=%.1f[sys];[mic][sys]amerge=inputs=2\" "
"-c:a libopus "
"-b:a 96k "
"%s")
+ mic-device
+ system-device
cj/recording-mic-boost
cj/recording-system-volume
filename)))
@@ -130,9 +176,10 @@ recording, otherwise use the default location in =video-recordings-dir'."
"*ffmpeg-audio-recording*"
ffmpeg-command))
(set-process-query-on-exit-flag cj/audio-recording-ffmpeg-process nil)
- (message "Started audio recording process (mic boost: %.1fx, system volume: %.1fx)."
- cj/recording-mic-boost cj/recording-system-volume))))
+ (message "Started audio recording to %s (mic: %.1fx, system: %.1fx)."
+ filename cj/recording-mic-boost cj/recording-system-volume))))
+;;;###autoload
(defun cj/video-recording-stop ()
"Stop the ffmpeg video recording process."
(interactive)
@@ -141,11 +188,12 @@ recording, otherwise use the default location in =video-recordings-dir'."
;; Use interrupt-process to send SIGINT (graceful termination)
(interrupt-process cj/video-recording-ffmpeg-process)
;; Give ffmpeg a moment to finalize the file
- (sit-for 1)
+ (sit-for 0.2)
(setq cj/video-recording-ffmpeg-process nil)
(message "Stopped video recording."))
(message "No video recording in progress.")))
+;;;###autoload
(defun cj/audio-recording-stop ()
"Stop the ffmpeg audio recording process."
(interactive)
@@ -154,11 +202,12 @@ recording, otherwise use the default location in =video-recordings-dir'."
;; Use interrupt-process to send SIGINT (graceful termination)
(interrupt-process cj/audio-recording-ffmpeg-process)
;; Give ffmpeg a moment to finalize the file
- (sit-for 1)
+ (sit-for 0.2)
(setq cj/audio-recording-ffmpeg-process nil)
(message "Stopped audio recording."))
(message "No audio recording in progress.")))
+;;;###autoload
(defun cj/recording-adjust-volumes ()
"Interactively adjust recording volume levels."
(interactive)
@@ -166,19 +215,22 @@ recording, otherwise use the default location in =video-recordings-dir'."
cj/recording-mic-boost))
(sys (read-number "System audio level (1.0 = normal, 0.5 = half): "
cj/recording-system-volume)))
- (customize-set-variable 'cj/recording-mic-boost mic)
- (customize-set-variable 'cj/recording-system-volume sys)
+ (setq cj/recording-mic-boost mic)
+ (setq cj/recording-system-volume sys)
(message "Recording levels updated - Mic: %.1fx, System: %.1fx" mic sys)))
;; Recording operations prefix and keymap
-(define-prefix-command 'cj/record-map nil
- "Keymap for video/audio recording operations.")
-(define-key cj/custom-keymap "r" 'cj/record-map)
-(define-key cj/record-map "V" 'cj/video-recording-stop)
-(define-key cj/record-map "v" 'cj/video-recording-start)
-(define-key cj/record-map "A" 'cj/audio-recording-stop)
-(define-key cj/record-map "a" 'cj/audio-recording-start)
-(define-key cj/record-map "l" 'cj/recording-adjust-volumes) ; 'l' for levels
+(defvar cj/record-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "V") #'cj/video-recording-stop)
+ (define-key map (kbd "v") #'cj/video-recording-start)
+ (define-key map (kbd "A") #'cj/audio-recording-stop)
+ (define-key map (kbd "a") #'cj/audio-recording-start)
+ (define-key map (kbd "l") #'cj/recording-adjust-volumes)
+ map)
+ "Keymap for video/audio recording operations.")
+
+;;;###autoload (keymap-set cj/custom-keymap "r" cj/record-map)
(provide 'video-audio-recording)
;;; video-audio-recording.el ends here.