2025-08-18 Cutting clips from videos with Emacs

I often want to show someone a clip from a video. When that someone is sitting next to me, I can just seek the right place in the video and hit “start”. But what if not? What if I’d like to upload the clip somewhere, or maybe even email it? Or just I don’t want to search for the right place, or risk showing too much of the video (which might contain spoilers, for example)?

Now, the first answer that comes to my mind is to extract the clip to a separate video file and play that instead. Of course, if you know me even a bit, you won’t be surprised that I’d like to do that from within the comfort of Emacs. While Emacs itself is not capable of playing videos, it can interface with mpv, and I already work with Subed mode and can drive video from it.

There are two things I need to be able to do what I want: select the beginning and end of the clip, and actually perform the trimming. The latter can be obviously achieved by ffmpeg, and while I don’t know what options I should give it to do that, I know that I’ve already solved that problem once. (Although it turned out that for some reason my solution stopped working – it still trims the video, but has some issues with embedding subtitles. I poked around and came up with another solution, which – instead of embedding the subtitles as a selectable track in the video – just hardcodes them on the image. This is not a good idea for generating a high-quality video with a movie or something, but is perfectly fine for just a short clip I’d like to share with someone. Also, I might want not to embed the subtitles at all – using C-u seems a natural way to achieve that. After a while I decided to flip it the other way round, so that using the subtitles won’t be embedded unless C-u is used.)

The only thing that remains is how to select the clip itself. I can easily pause the video at any desired moment (possibly even moving forward or backward by frame) and just tell Emacs “this is the place I want my clip to start/end”.

So, let’s get coding.

asking on the group:

(defvar subed-clip-beginning nil
  "The beginning position to clip.")

(defvar subed-clip-width 320
  "The width of the clips generated.")

(defun subed-clip-mark-begin ()
  "Make the current point the beginning of the clip."
  (interactive)
  (setq subed-clip-beginning subed-mpv-playback-position))

(defun subed-clip-mark-end (embed-subtitles)
  "Make the current point the end of the clip and perform the clipping.
With an interactive argument, embed the subtitles."
  (interactive "P")
  (let ((args `("-y"
                "-i" ,subed-mpv-media-file
                "-ss" ,(format "%dms" subed-clip-beginning)
                "-to" ,(format "%dms" subed-mpv-playback-position)
                "-filter:v"
                ,(format "%s%s"
                         (if embed-subtitles
                             (format "subtitles=%s,"
                                     (buffer-file-name))
                           "")
                         (format "scale=%d:trunc(ow/a/2)*2"
                                 subed-clip-width))
                "-c:v" "libx264"
                "-c:a" "copy"
                ,(file-name-concat "clip.mp4"))))
    (apply #'call-process "ffmpeg" nil nil nil args))
  (message "Clipping done."))

As you can see, these functions are very simplistic. I basically took the code I wrote a year ago and made it even simpler. There is no error checking – if you call subed-clip-mark-end when the current moment is before the one selected with subed-clip-mark-begin, the clipping just silently fails. This is, however, just a quick hack put together in 15 minutes, not a package ready for distribution. If you want similar functionality for yourself, just feel free to copy my code and modify it to suit your needs.

CategoryEnglish, CategoryBlog, CategoryEmacs, CategorySubtitles