Here is a generic video downloader for emacs-w3m that supports all videos on all sites, using the external program youtube-dl. The function spawns an asychronous process to perform the download, so you can continue using emacs for other work, and you can download multiple videos simultaneously. Each download is documented in a unique w3m-download-video buffer which indicates the download operation status and progress. You can customize the youtube-dl download options for any site by modifying or adding entries to the defcustom w3m-download-video-alist.

The interactive function names are w3m-download-video and w3m-download-video-at-point, which you can bind to whatever key combination you think appropriate.

Do note that emacs-w3m already has functions w3m-lnum-download-this-url and w3m-download.

The revision history of this wiki page contains two other methods for downloading video, but both are very old and outdated.

(defcustom w3m-download-video-alist
  '(("\\.youtube\\." . "-f 18 --newline"))
  "*An alist of arguments to use for downloading from specific urls.

Each element should be of the form (URL . ARGS),
for example (\"\\.youtube\\.\" . \"-f 18\").

Refer to `man(1) youtube-dl' for information on available arguments."
  :group 'w3m
  :type '(repeat
      (cons :format "%v" :indent 12
        (string :format "url base:            %v")
        (string :format "args for youtube-dl: %v"))))

(defun w3m-download-video (url)
  "Invoke `youtube-dl' in a sub-process to download a video."
  (if (not (w3m-url-valid url))
    (error "Invalid URL")
  (when (string-match "\\(\\&list=[^&]+\\)" url)
    (setq url
        (substring-no-properties url nil (match-beginning 0))
        (substring-no-properties url (match-end 0)))))
  (let* (proc
         (buf (generate-new-buffer "*w3m-download-video*"))
         (base (and (string-match "//\\([^/]+\\)/" url)
           (substring-no-properties url
             (match-beginning 1) (match-end 1))))
         (args (catch 'found-replacement
           (dolist (elem w3m-download-video-alist "--")
             (when (string-match (car elem) base)
               (throw 'found-replacement (cdr elem)))))))
    (with-current-buffer buf
      ; How can I customize this buffer so incoming 'C-m' will be
      ; dynamically converted to 'C-j' in order to appear correctly
      ; as new-lines?
      ; (set-buffer-file-coding-system 'utf-8-dos)
      ; (set-buffer-file-coding-system 'utf-8-mac)
      (insert (current-time-string)
        "\n  youtube-dl " args " " url "\n\n")
      ; NOTE: There does exist a function `w3m-process-do' to evaluate
      ;       lisp code asyncronously.
      (setq proc
        (start-process "w3m-download-video" buf "youtube-dl" args url)))
    (w3m-message "Requesting download.")
    (set-process-sentinel proc
      (lambda (proc event)
        (let ((buf (process-buffer proc)))
         (with-current-buffer buf (insert event))
          ((string-match "^finished" event)
               "Download complete. Check buffer %s for details." buf))
          ((string-match "^open" event) t)
          (t (message
               "Download error. Check buffer %s for details." buf)))))))))

(defun w3m-download-video-at-point ()
  "Invoke `youtube-dl' in a sub-process to download the video at point."
  (let ((url (w3m-anchor)))
   (if (not url)
     (user-error "No url found at point.")
    (w3m-download-video url))))


2018-04-12: updated code to handle youtube links on playlist pages