diff options
Diffstat (limited to 'emacs/.emacs.d')
-rw-r--r-- | emacs/.emacs.d/lisp/my/my-media-segment.el | 77 |
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. |