如何计算 01:12:15 这种时间格式的时间差?

我想写一个Emacs命令来使用ffmpeg截取视频的一个片段。 命令如下:

 ffmpeg -i 荡寇风云.God.of.War.2017.HD720P.X264.AAC.Mandarin.CHS.mp4 -ss 01:00:40 -t 00:07:00 -codec copy output.mp4

这其中 -t 这个时间戳是截取视频的长度。是计算截取点前后的两个时间点的差值。 我想问一下,Elisp下有什么函数或者包能够计算这个的么?

先转成unix时间戳再计算

之前在reddit上看到过这个问题,calc可以直接算

Elisp里面要怎么操作转换?Emacs里我搜索 unix.*time 只找到 calc-unix-time.

Calc看到有命令似乎可以做时间减法,但是貌似不能操作这种只有时间戳的格式。而且也没有elisp函数。只有Calc里面的命令。可能是我没有发现找到。

自己计算一下好了,split-string 分割一下,然后 string-to-number 转化成数字,最后算一下就 OK 了。

方法是对 但不是函数式呀

可以用mapc 遍历每一个字符

遇到冒号就*60

楼下还有别的方法吗

在没有找到现成好用的函数方法前,自己先写一个将就吧。

(defun ffmpeg-subtract-timestamps (start-timestamp end-timestamp)
  "Subtract END-TIMESTAMP with START-TIMESTAMP."
  (let* ((start-t (mapcar 'string-to-number (split-string start-timestamp ":")))
         (start-hour (car start-t))
         (start-minute (cadr start-t))
         (start-second (caddr start-t))
         (end-t (mapcar 'string-to-number (split-string end-timestamp ":")))
         (end-hour (car end-t))
         (end-minute (cadr end-t))
         (end-second (caddr end-t))
         (subtract-t (list (- end-hour start-hour)
                           (- end-minute start-minute)
                           (- end-second start-second))))
    (when (< (caddr subtract-t) 0)
      (set 'subtract-t (list (car subtract-t)
                             (1- (cadr subtract-t))
                             (- (caddr subtract-t)))))
    (when (< (cadr subtract-t) 0)
      (set 'subtract-t (list (1- (car subtract-t))
                             (- (cadr subtract-t))
                             (caddr subtract-t))))
    subtract-t))

(ffmpeg-subtract-timestamps "00:11:25" "00:12:12")

先分享下现在能用的代码方案。

(defun ffmpeg-subtract-timestamps (start-timestamp end-timestamp)
  "Subtract END-TIMESTAMP with START-TIMESTAMP."
  (let* ((start-t (mapcar 'string-to-number (split-string start-timestamp ":")))
         (start-hour (car start-t))
         (start-minute (cadr start-t))
         (start-second (caddr start-t))
         (end-t (mapcar 'string-to-number (split-string end-timestamp ":")))
         (end-hour (car end-t))
         (end-minute (cadr end-t))
         (end-second (caddr end-t))
         (subtract-t (list (- end-hour start-hour)
                           (- end-minute start-minute)
                           (- end-second start-second))))
    (when (< (caddr subtract-t) 0)
      (set 'subtract-t (list (car subtract-t)
                             (1- (cadr subtract-t))
                             (- (caddr subtract-t)))))
    (when (< (cadr subtract-t) 0)
      (set 'subtract-t (list (1- (car subtract-t))
                             (- (cadr subtract-t))
                             (caddr subtract-t))))
    subtract-t))

;; (ffmpeg-subtract-timestamps "00:11:25" "00:12:12")

(defun ffmpeg-cut-clip (input-filename start-timestamp end-timestamp output-filename)
  (interactive (list
                (read-file-name "FFmpeg input filename: ")
                (read-string "FFmpeg start timestamp: ")
                (read-string "FFmpeg end timestamp: ")
                (read-file-name "FFmpeg output filename: ")))
  (make-process
   :name "ffmpeg cut clip"
   ;; "ffmpeg -i input-filename -ss start-timestamp -t time-timestamp -codec copy output-filename"
   :command (list "ffmpeg"
                  "-i" input-filename
                  "-ss" start-timestamp
                  "-t" (ffmpeg-subtract-timestamps start-timestamp end-timestamp)
                  "-codec copy"
                  output-filename)
   :buffer "*ffmpeg-cut-clip*"
   :sentinel (lambda (proc event)
               (message "FFmpeg cut video clip finished."))))

-t 后面应该可以直接接秒的吧,我稍微改了一点点。

(defun ffmpeg-subtract-timestamps (start-timestamp end-timestamp)
  "Subtract END-TIMESTAMP with START-TIMESTAMP."
  (let ((start 0)
        (end 0))
    (dolist (time (mapcar #'string-to-number (split-string start-timestamp ":")))
      (setq start (+ time (* start 60))))
    (dolist (time (mapcar #'string-to-number (split-string end-timestamp ":")))
      (setq end (+ time (* end 60))))
    (- end start)))

还真是,可以直接秒。能接受三种格式

       The following examples are all valid time duration:

       55  55 seconds

       12:03:45
           12 hours, 03 minutes and 45 seconds

       23.189
           23.189 seconds
(ffmpeg-subtract-timestamps "00:11:25" "00:12:12")

(0 0 13)

没有通过测试呦

正确的结果是 (0 0 47)

绣 代码


(let( (sum 0) (acc 0) )
  (mapc
   (lambda (x)
     (if (and (<= (- x ?0) 9) (>= (- x ?0)  0))
	 (setq acc (+ (* 10 acc)(- x ?0) ))
       (setq sum (+ (* sum 60) acc)
	     acc 0)))
   "00:02:34")
  (setq sum (+ (* sum 60) acc))
  sum)


(let ((time "")  (num 154))
  (dotimes ( i 2)
    (setq time (concat (format ":%02d" (% num 60)) time)
          num (/ num 60)))
  (setq time (concat (format "%02d" num ) time))
  time)


另一个实现吧,供参考,不过不支持毫秒

(defun ffmpeg-subtract-timestamps (start-timestamp end-timestamp)
  "Subtract END-TIMESTAMP with START-TIMESTAMP."
  (time-subtract
   (encode-time (parse-time-string
                 (concat "2020-01-01T" end-timestamp)))
   (encode-time (parse-time-string
                 (concat "2020-01-01T" start-timestamp)))))

这个实现看起来比较简介直观。就这个了。

看不懂代码。。。。我还是太菜了