executable_peertube 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #!/usr/bin/env -S guile --no-auto-compile -e main -s
  2. !#
  3. ;;; convert-music --- Convert video clips to audio only
  4. ;;; Copyright © 2019, 2022 Oleg Pykhalov <go.wigust@gmail.com>
  5. ;;;
  6. ;;; This file is part of convert-music.
  7. ;;;
  8. ;;; convert-music is free software; you can redistribute it and/or modify it
  9. ;;; under the terms of the GNU General Public License as published by
  10. ;;; the Free Software Foundation; either version 3 of the License, or (at
  11. ;;; your option) any later version.
  12. ;;;
  13. ;;; convert-music is distributed in the hope that it will be useful, but
  14. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. ;;; GNU General Public License for more details.
  17. ;;;
  18. ;;; You should have received a copy of the GNU General Public License
  19. ;;; along with convert-music. If not, see <http://www.gnu.org/licenses/>.
  20. ;; Convert video clips in /srv/music directory to audio files without a video
  21. ;; part and store them in /srv/audio directory. To do that, run:
  22. ;;
  23. ;; peertube /srv/music
  24. (use-modules (ice-9 format)
  25. (ice-9 ftw)
  26. (ice-9 match)
  27. (ice-9 popen)
  28. (ice-9 rdelim)
  29. (ice-9 readline)
  30. (json)
  31. (srfi srfi-1)
  32. (srfi srfi-26)
  33. (srfi srfi-34)
  34. (srfi srfi-37)
  35. (guix build utils))
  36. (define (list-files dir)
  37. (filter (match-lambda
  38. ((name #(_ _ _ _ _ _ _ _ _ _ _ _ _ 'regular _ _ _ _)) name)
  39. (_ #f))
  40. (file-system-tree dir)))
  41. (define %options
  42. (let ((display-and-exit-proc (lambda (msg)
  43. (lambda (opt name arg loads)
  44. (display msg) (quit)))))
  45. (list (option '(#\v "version") #f #f
  46. (display-and-exit-proc "convert-music version 0.0.1\n"))
  47. (option '(#\h "help") #f #f
  48. (display-and-exit-proc
  49. "Usage: convert-music /srv/music /srv/audio ...")))))
  50. (define %default-options
  51. '())
  52. (define %peertube-api-url
  53. (and=> (getenv "PEERTUBE_API_URL")
  54. (lambda (peertube-api-url)
  55. peertube-api-url)))
  56. (define %peertube-username
  57. (and=> (getenv "PEERTUBE_USERNAME")
  58. (lambda (peertube-username)
  59. peertube-username)))
  60. (define %peertube-password
  61. (and=> (getenv "PEERTUBE_PASSWORD")
  62. (lambda (peertube-password)
  63. peertube-password)))
  64. (define %peertube-channel-id
  65. (and=> (getenv "PEERTUBE_CHANNEL_ID")
  66. (lambda (peertube-channel-id)
  67. peertube-channel-id)))
  68. (define %peertube-category
  69. (and=> (getenv "PEERTUBE_CATEGORY")
  70. (lambda (peertube-category)
  71. peertube-category)))
  72. (define %peertube-playlist-id
  73. (and=> (getenv "PEERTUBE_PLAYLIST_ID")
  74. (lambda (peertube-playlist-id)
  75. peertube-playlist-id)))
  76. (define %peertube-privacy
  77. (and=> (getenv "PEERTUBE_PRIVACY")
  78. (lambda (peertube-privacy)
  79. peertube-privacy)))
  80. (define (peertube-client-id)
  81. (let* ((port (open-pipe* OPEN_READ "curl"
  82. (string-append
  83. %peertube-api-url "/oauth-clients/local")
  84. "--silent"))
  85. (output (read-string port)))
  86. (close-port port)
  87. (string-trim-right output #\newline)))
  88. (define (peertube-access-token client-id client-secret)
  89. (let* ((port (open-pipe* OPEN_READ "curl"
  90. (string-append %peertube-api-url "/users/token")
  91. "--silent"
  92. "--data" (format #f "client_id=~a" client-id)
  93. "--data" (format #f "client_secret=~a" client-secret)
  94. "--data" "grant_type=password"
  95. "--data" "response_type=code"
  96. "--data" (format #f "username=~a" %peertube-username)
  97. "--data" (format #f "password=~a" %peertube-password)))
  98. (output (read-string port)))
  99. (close-port port)
  100. (string-trim-right output #\newline)))
  101. (define (append-to-file name body)
  102. (let ((file (open-file name "a")))
  103. (display body file)
  104. (close-port file)))
  105. (define (main . args)
  106. (define opts
  107. (args-fold (cdr (program-arguments))
  108. %options
  109. (lambda (opt name arg loads)
  110. (error "Unrecognized option `~A'" name))
  111. (lambda (op loads)
  112. (cons op loads))
  113. %default-options))
  114. (define input-directory
  115. (first (reverse opts)))
  116. (define client-id+secret
  117. (json-string->scm (peertube-client-id)))
  118. (define client-id
  119. (assoc-ref client-id+secret "client_id"))
  120. (define client-secret
  121. (assoc-ref client-id+secret "client_secret"))
  122. (define access-token
  123. (assoc-ref
  124. (json-string->scm
  125. (peertube-access-token client-id client-secret))
  126. "access_token"))
  127. (for-each (lambda (file)
  128. (match file
  129. ((n ... ext)
  130. (let* ((input (string-append input-directory "/"
  131. (string-join file ".")))
  132. (output-file-name
  133. (match (string-split (basename input) #\.)
  134. ((file-name ... file-extension)
  135. (string-join file-name "."))
  136. ((file-name file-extension)
  137. file-name)))
  138. (video-upload-output (string-append output-file-name ".json")))
  139. (if (any (lambda (file)
  140. (string= file input))
  141. (string-split
  142. (with-input-from-file "peertube.log"
  143. read-string)
  144. #\newline))
  145. (format #t "~%Skip already uploaded ~a file.~%" input)
  146. (begin
  147. (format #t "input: ~a~%" input)
  148. (format #t "output: ~a~%" output-file-name)
  149. (guard (c ((invoke-error? c)
  150. (report-invoke-error c)
  151. (append-to-file "peertube-error.log" (string-append "\n" input))
  152. #f))
  153. (invoke
  154. "curl" (string-append %peertube-api-url "/videos/upload")
  155. "--fail"
  156. "--max-time" "6000"
  157. "--header" (format #f "Authorization: Bearer ~a" access-token)
  158. "--form" (format #f "videofile=@~a" input)
  159. "--form" (format #f "name=~a" output-file-name)
  160. "--form" (format #f "channelId=~a" %peertube-channel-id)
  161. "--form" (format #f "privacy=~a" %peertube-privacy)
  162. "--form" (format #f "category=~a" %peertube-category)
  163. "--form" "waitTranscoding=1"
  164. "--output" video-upload-output))
  165. (display "\nSleep for 30 to wait for API.\n")
  166. (sleep 30)
  167. (let ((uuid (assoc-ref (assoc-ref (json-string->scm
  168. (with-input-from-file video-upload-output
  169. read-string))
  170. "video")
  171. "uuid")))
  172. (guard (c ((invoke-error? c)
  173. (report-invoke-error c)
  174. (append-to-file "peertube-playlist-error.log" (string-append "\n" input))
  175. #f))
  176. (invoke "curl"
  177. (string-append %peertube-api-url "/video-playlists/" %peertube-playlist-id "/videos")
  178. "--fail"
  179. "--header" (format #f "Authorization: Bearer ~a" access-token)
  180. "--data" (format #f "videoId=~a" uuid))))
  181. (let loop ()
  182. (if (= (system* "pgrep" "--full" "--list-full" "ffmpeg")
  183. 256)
  184. #t
  185. (begin
  186. (display "Wait until ffmpeg processes do not exist.\n")
  187. (sleep 30)
  188. (loop))))
  189. (newline)
  190. (append-to-file "peertube.log" (string-append "\n" input))))))))
  191. (map (cut string-split <> #\.)
  192. (map (match-lambda ((file _ ...) file))
  193. (list-files input-directory)))))