executable_convert-music 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. ;; convert-music /srv/music /srv/audio
  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-37))
  34. (define (list-files dir)
  35. (filter (match-lambda
  36. ((name #(_ _ _ _ _ _ _ _ _ _ _ _ _ 'regular _ _ _ _)) name)
  37. (_ #f))
  38. (file-system-tree dir)))
  39. (define %options
  40. (let ((display-and-exit-proc (lambda (msg)
  41. (lambda (opt name arg loads)
  42. (display msg) (quit)))))
  43. (list (option '(#\v "version") #f #f
  44. (display-and-exit-proc "convert-music version 0.0.1\n"))
  45. (option '(#\h "help") #f #f
  46. (display-and-exit-proc
  47. "Usage: convert-music /srv/music /srv/audio ...")))))
  48. (define %default-options
  49. '())
  50. (define (codec-name->file-extension codec-name)
  51. (case codec-name
  52. ((opus) ".opus")
  53. ((vorbis) ".ogg")
  54. ((aac) ".aac")
  55. (else #f)))
  56. (define (main . args)
  57. (define opts
  58. (args-fold (cdr (program-arguments))
  59. %options
  60. (lambda (opt name arg loads)
  61. (error "Unrecognized option `~A'" name))
  62. (lambda (op loads)
  63. (cons op loads))
  64. %default-options))
  65. (define input-directory
  66. (first (reverse opts)))
  67. (define output-directory
  68. (second (reverse opts)))
  69. (for-each (lambda (file)
  70. (match file
  71. ((n ... ext)
  72. (let* ((input (string-append input-directory "/"
  73. (string-join file ".")))
  74. (output-file-name
  75. (match (string-split (basename input) #\.)
  76. ((file-name ... file-extension)
  77. (string-join file-name "."))
  78. ((file-name file-extension)
  79. file-name))))
  80. (let* ((port (open-pipe* OPEN_READ "ffprobe"
  81. "-show_streams"
  82. "-loglevel" "error"
  83. "-print_format" "json"
  84. input))
  85. (output (read-string port)))
  86. (close-port port)
  87. (for-each (lambda (stream)
  88. (when (string= (assoc-ref stream "codec_type")
  89. "audio")
  90. (let ((output
  91. (string-append
  92. output-directory "/"
  93. output-file-name
  94. (codec-name->file-extension
  95. (string->symbol
  96. (assoc-ref stream "codec_name"))))))
  97. (format #t "input: ~a~%"
  98. input)
  99. (format #t "format: ~a~%"
  100. (assoc-ref stream "codec_name"))
  101. (format #t "output: ~a~%"
  102. output)
  103. (unless (file-exists? output)
  104. (unless
  105. (= 0 (system*
  106. "ffmpeg"
  107. "-loglevel" "quiet"
  108. "-i" input
  109. "-vn" ;no video
  110. "-c:a" "copy" ;copy audio
  111. output))
  112. (exit 1)))
  113. (newline))))
  114. (array->list
  115. (assoc-ref (json-string->scm
  116. (string-trim-right output #\newline))
  117. "streams"))))))))
  118. (map (cut string-split <> #\.)
  119. (map (match-lambda ((file _ ...) file))
  120. (list-files input-directory)))))