commit 126a6fb65b52e2bb95aee94f42f6b740776cbd63 Spenser Truex <struex0@gmail.com> 2018-07-31 10:02:01 -0700 ffmpeg mp3 to mp4 via bash interaction.
README.md | 5 +++++ librivox.asd | 6 ++++-- persistent.lisp | 0 rss.asd | 6 ++++++ rss/rss.lisp | 27 +++++++++++++++++++++++++++ src/ffmpeg.lisp | 46 ++++++++++++++++++++++++++++++++++++++++++++++ src/librivox.lisp | 5 ++++- utils.lisp | 7 +++++++ youtube.asd | 6 ++++++ youtube/utils.lisp | 1 + youtube/youtube.lisp | 3 +++ 11 files changed, 109 insertions(+), 3 deletions(-)
diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2ed1a9 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Requirements: +`mp3info` +`ffmpeg` +`bash` +`Quicklisp` diff --git a/librivox.asd b/librivox.asd index 0770788..86176dd 100644 --- a/librivox.asd +++ b/librivox.asd @@ -1,6 +1,8 @@ (asdf:defsystem :librivox :serial t - :depends-on (:drakma :rss :youtube) + :depends-on (:drakma :uiop :rss :youtube) :description "Librivox auto downloader/youtube uploader." :components ((:file "utils") - (:file "src/librivox"))) + (:file "src/librivox") + (:file "src/ffmpeg"))) + diff --git a/persistent.lisp b/persistent.lisp new file mode 100644 index 0000000..e69de29 diff --git a/rss.asd b/rss.asd new file mode 100644 index 0000000..c34414c --- /dev/null +++ b/rss.asd @@ -0,0 +1,6 @@ +(asdf:defsystem :rss + :serial t + :description "RSS feed reader." + :depends-on (:drakma :cl-feedparser) + :components ((:file "utils") + (:file "rss/rss"))) diff --git a/rss/rss.lisp b/rss/rss.lisp new file mode 100644 index 0000000..226b3f9 --- /dev/null +++ b/rss/rss.lisp @@ -0,0 +1,27 @@ +(defpackage :rss + (:use :cl :drakma :utils :cl-feedparser) + (:import-from :drakma + :http-request) + (:import-from :utils + :remove-after) + ;(:import-from :feedparser) + ;(:export ) + ) +(in-package :rss) +(defvar *persistence* "persistent.lisp") +#|(let ((x (parse-feed "https://librivox.org/rss/latest_releases"))) + (loop for hk being the hash-key in x + for hv being the hash-value in x + collect (cons hk hv))) +(defun parse-feed (url) + (feedparser:parse-feed (http-request url))) +(defun update (url) + (remove-after (previous-update) + (readable-feed (parse-feed url)) + :test #'equal))|# +(defun previous-update () + "Get the most recent update." + (with-open-file (s *persistence* + :direction :input + :if-does-not-exist :create) + (read s nil nil))) diff --git a/src/ffmpeg.lisp b/src/ffmpeg.lisp new file mode 100644 index 0000000..044f3e3 --- /dev/null +++ b/src/ffmpeg.lisp @@ -0,0 +1,46 @@ +(in-package :librivox) +(defvar *bash-output* *debug-io*) +(defparameter *seconds* 0 "The time in seconds of the entire book.") +(defvar *downloads-dir* "/home/jose/common-lisp/librivox/downloads/") +(defun run-lines (&rest code-strings) + (mapcar #'(lambda (x) (run-program (format nil x *downloads-dir*) :output *bash-output*)) + code-strings)) +(defun nth-digit (digit number base) + (if (= 0 digit) + (mod number base) + (nth-digit (1- digit) (floor number base) base))) +(defun hours (seconds) + (/ (- seconds (* 60 (minutes seconds)) (seconds seconds)) + 60 60)) +(defun minutes (seconds) + (nth-digit 1 seconds 60)) +(defun seconds (seconds) + (nth-digit 0 seconds 60)) + +(defun convert (image-pathname output-pathname) + "Convert the zip to video." + ;; ~A for the download directory, ~:*~A after the first. + (let ((output-pathname (merge-pathnames output-pathname *downloads-dir*))) + (unwind-protect (let ((image-pathname (merge-pathnames image-pathname *downloads-dir*))) + (run-lines "unzip ~A*.zip -d ~:*~A" + "for f in ~A*.mp3; do echo \"file '$f'\" >> ~:*~Aconcat.txt; done" + "ffmpeg -f concat -safe 0 -i ~Aconcat.txt -c copy ~:*~Aoutput1.mp3") + (setf *seconds* (parse-integer (run-program (format nil "mp3info -p \"%S\" ~Aoutput1.mp3" *downloads-dir*) ; + :output 'string) + :junk-allowed t)) + (run-lines (format nil "ffmpeg -loop 1 -i ~A -t ~D:~D:~D -c mjpeg ~~Atemp.mp4" ; + image-pathname + (hours *seconds*) + (minutes *seconds*) + (seconds *seconds*))) + + (run-lines (format nil"ffmpeg -i ~~Atemp.mp4 -i ~~:*~~Aoutput1.mp3 -c copy ~~:*~~Aconverted/~A" + output-pathname) + "rm ~Atemp.mp4" + "rm ~A*.mp3" + "rm ~Aconcat.txt")) + (run-lines "rm ~Atemp.mp4" + "rm ~A*.mp3" + "rm ~Aconcat.txt")))) +;;; Example input: (convert "image.jpg" "final-test-probably.mp4") + diff --git a/src/librivox.lisp b/src/librivox.lisp index 5f3f857..c12a024 100644 --- a/src/librivox.lisp +++ b/src/librivox.lisp @@ -1,3 +1,6 @@ (defpackage :librivox - (:use :cl :drakma :utils)) + (:use :cl :drakma :utils :uiop) + (:import-from :uiop + :run-program)) (in-package :librivox) +(defvar *url* "https://librivox.org/rss/latest_releases") diff --git a/utils.lisp b/utils.lisp new file mode 100644 index 0000000..2278d16 --- /dev/null +++ b/utils.lisp @@ -0,0 +1,7 @@ +(defpackage :utils + (:use :cl :cl-user) + (:export :remove-after)) +(in-package :utils) + +(defun remove-after (item list &key (test #'eql)) + (subseq list (search (list item) list :test test))) diff --git a/youtube.asd b/youtube.asd new file mode 100644 index 0000000..9bae284 --- /dev/null +++ b/youtube.asd @@ -0,0 +1,6 @@ +(asdf:defsystem :youtube + :serial t + :description "Youtube data api." + :depends-on (:drakma) + :components ((:file "utils") + (:file "youtube/youtube"))) diff --git a/youtube/utils.lisp b/youtube/utils.lisp new file mode 120000 index 0000000..5b43057 --- /dev/null +++ b/youtube/utils.lisp @@ -0,0 +1 @@ +utils.lisp \ No newline at end of file diff --git a/youtube/youtube.lisp b/youtube/youtube.lisp new file mode 100644 index 0000000..2e0a9b2 --- /dev/null +++ b/youtube/youtube.lisp @@ -0,0 +1,3 @@ +(defpackage :youtube + (:use :cl :drakma :utils)) +(in-package :youtube)