aboutsummaryrefslogtreecommitdiff
path: root/emacs/.emacs.d
diff options
context:
space:
mode:
Diffstat (limited to 'emacs/.emacs.d')
-rw-r--r--emacs/.emacs.d/lisp/my/my-media-segment.el77
1 files changed, 77 insertions, 0 deletions
diff --git a/emacs/.emacs.d/lisp/my/my-media-segment.el b/emacs/.emacs.d/lisp/my/my-media-segment.el
index 003953a..9431624 100644
--- a/emacs/.emacs.d/lisp/my/my-media-segment.el
+++ b/emacs/.emacs.d/lisp/my/my-media-segment.el
@@ -50,6 +50,83 @@ The process can be started by applying 'start-process' on START-PROCESS-ARGS."
(when my-media-segment-queued-jobs
(funcall (pop my-media-segment-queued-jobs))))
+(defun my-ffmpeg-split-file (file-name split-at)
+ "Split FILE-NAME at SPLIT-AT into two files."
+ (let* ((name-no-ext (file-name-sans-extension file-name))
+ (ext (file-name-extension file-name))
+ (file-name-1 (make-temp-file (format "%s-1-" name-no-ext) nil
+ (format ".%s" ext)))
+ (file-name-2 (make-temp-file (format "%s-2-" name-no-ext) nil
+ (format ".%s" ext))))
+ (message "Splitting %s at %s into %s and %s..."
+ file-name split-at file-name-1 file-name-2)
+ (set-process-sentinel
+ (start-process (format "ffmpeg-%s" file-name)
+ (format "*ffmpeg-%s*" file-name)
+ "ffmpeg"
+ "-i" file-name
+ "-to" split-at "-c" "copy" file-name-1
+ "-ss" split-at "-c" "copy" file-name-2
+ "-y")
+ (lambda (proc event)
+ (let ((status (process-exit-status proc)))
+ (if (eq status 0)
+ (progn
+ (message "Splitting %s at %s into %s and %s... Done"
+ file-name split-at file-name-1 file-name-2))
+ (message "Splitting %s at %s into %s and %s... Failed: %s"
+ file-name split-at file-name-1 file-name-2 event)))))))
+
+(defun my-dired-do-ffmpeg-split-file ()
+ (interactive)
+ (seq-do
+ (lambda (file)
+ (my-ffmpeg-split-file file (read-string
+ (format "Split %s at: " file))))
+ (dired-get-marked-files)))
+
+(defun my-segment-media-file-2 (media-file-name info-file-name)
+ "Run ffmpeg to segment MEDIA-FILE-NAME according to INFO-FILE-NAME in one go.
+
+Much faster than my-segment-media-file or my-segment-media-file-1."
+ (interactive (list
+ (read-file-name "Choose media file: ")
+ (read-file-name
+ "Choose description file (.info.json or .description): ")))
+ (let* ((dir (file-name-sans-extension (expand-file-name media-file-name)))
+ (info (my-get-media-segments info-file-name))
+ (total (length info))
+ (pad (1+ (floor (log10 total))))
+ (idx 0)
+ (args `("-i" ,(expand-file-name media-file-name))))
+ (ignore-errors (dired-create-directory dir))
+ (dolist (media info)
+ (setq idx (1+ idx))
+ (let* ((title (plist-get media :title))
+ (start (plist-get media :start))
+ (end (plist-get media :end)))
+ (setq args (append args
+ `("-ss" ,start)
+ (when end `("-to" ,end))
+ `("-c" "copy"
+ ,(format
+ (format "%%s/%%0%dd-%%s.%%s" pad) dir idx title
+ (file-name-extension media-file-name)))))
+ (message "Will cut %s-%s to %s (%d/%d)..."
+ start (or end "") title idx total)))
+ (set-process-sentinel
+ (apply 'start-process
+ (append `(,(format "ffmpeg-%s" media-file-name)
+ ,(format "*ffmpeg-%s*" media-file-name)
+ "ffmpeg")
+ args))
+ (lambda (proc event)
+ (let ((status (process-exit-status proc)))
+ (if (eq status 0)
+ (progn
+ (message "Cutting %s: All DONE" media-file-name))
+ (message "Cutting %s FAILED: %s" media-file-name event)))))))
+
(defun my-segment-media-file-1 (media-file-name info-file-name)
"Run ffmpeg asynchronously to segment file-name according to description.