DEV Community

Vee Satayamas
Vee Satayamas

Posted on

1

A script for downloading PeerTube videos

Since peertube.social is closing down, I need a script for downloading all of my videos. I searched for this for a few minutes. I felt that it exists but I can't find, so I wrote mine in Common Lisp.

It probably works on other Common Lisp implementations too but I only tested on SBCL 2.0.1-5.fc34.

;; How to run
;; sbcl --load download-peertube-videos.lisp

(ql:quickload :jonathan)
(ql:quickload :dexador)
(ql:quickload :alexandria)
(ql:quickload :asdf)

(import 'alexandria:assoc-value)

(defparameter *username* "peertube-user-name")
(defparameter *hostname* "peertube.social")
(defparameter *get-videos-url* (format nil "https://~A/api/v1/accounts/~A/videos" *hostname* *username*))

(defparameter *videos-info* (assoc-value (jonathan:parse (dex:get *get-videos-url*)
                                                         :as :alist)
                                         "data"
                                         :test 'equal))

(defparameter *total* (assoc-value (jonathan:parse (dex:get (format nil "https://~A/api/v1/accounts/~A/videos" *hostname* *username*))
                                                   :as :alist)
                                   "total"
                                   :test 'equal))

(defparameter *count* 5)

(defun get-video-id (video-info)
  (assoc-value video-info "id" :test 'equal))

(defun get-video-json (video-id)
  (let ((video-info-url (format nil "https://~A/api/v1/videos/~A" *hostname* video-id)))
    (dex:get video-info-url)))

(defun download-video (video-details)
  (let* ((files (assoc-value video-details "files" :test 'equal))
         (download-url (assoc-value (car files) "fileDownloadUrl" :test 'equal))
         (cmd (format nil "wget ~A" download-url)))
    (format t "CMD: ~A~%" cmd)
    (uiop:run-program cmd :output t)))

(defun save-metadata (video-id video-json)
  (with-open-file (f (format nil "~A.json" video-id)
                     :direction :output
                     :if-exists :supersede
                     :if-does-not-exist :create)
    (write-string video-json f)))

(defun download-video-with-metadata (video-info)
  (let* ((video-id (get-video-id video-info))
         (video-json (get-video-json video-id))
         (video-details (jonathan:parse video-json
                                        :as :alist)))
    (save-metadata video-id video-json)
    (download-video video-details)))

(let ((i 0))
  (loop while (< i *total*)
        do
           (let* ((url (format nil "https://~A/api/v1/accounts/~A/videos?start=~A&count=~A" *hostname* *username* i *count*))

                  (videos-json (dex:get url))
                  (videos-alist (jonathan:parse videos-json :as :alist))
                  (videos-info (assoc-value videos-alist "data" :test 'equal)))
             (format t "*** i = ~A~%" i)
             (loop for video-info in videos-info
                   do
                      (download-video-with-metadata video-info)))
           (setq i (+ i *count*))))
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up