92 lines
1.9 KiB
Ruby
Executable file
92 lines
1.9 KiB
Ruby
Executable file
#!/usr/bin/env ruby
|
|
#
|
|
# youtube-snarf-audio - Extract audio from YouTube videos
|
|
#
|
|
# Downloads YouTube videos and extracts audio to m4a format.
|
|
# Accepts YouTube URLs or just video IDs as arguments.
|
|
# Skips audio extraction if output file already exists.
|
|
#
|
|
# Usage: youtube-snarf-audio <youtube-url> [<youtube-url> ...]
|
|
#
|
|
# Examples:
|
|
# youtube-snarf-audio https://youtube.com/watch?v=abc123
|
|
# youtube-snarf-audio abc123
|
|
#
|
|
# Requires: youtube-dl, ffmpeg
|
|
|
|
require 'cgi'
|
|
require 'faraday'
|
|
require 'rack'
|
|
require 'uri'
|
|
|
|
def main
|
|
while youtube_url = ARGV.shift
|
|
puts ">>> Snarfing audio from #{youtube_url}..."
|
|
if YouTubeSnarfer.snarf(youtube_url)
|
|
sleep 60
|
|
end
|
|
end
|
|
end
|
|
|
|
class YouTubeSnarfer
|
|
|
|
attr_reader :url, :video_filename
|
|
|
|
def self.snarf(url)
|
|
new(url).snarf
|
|
end
|
|
|
|
def initialize(url)
|
|
@url = url
|
|
unless @url =~ /^http/
|
|
@url = "http://youtube.com/watch?v=#{@url}"
|
|
end
|
|
end
|
|
|
|
def snarf
|
|
encode_audio
|
|
end
|
|
|
|
def title
|
|
video_filename.sub(/\s*-\w+.mp4\s*$/, '')
|
|
end
|
|
|
|
def audio_filename
|
|
"#{title}.m4a"
|
|
end
|
|
|
|
def encode_audio
|
|
save_video
|
|
if File.exists?(audio_filename)
|
|
puts ">>> Skipping, #{audio_filename} already exists. Delete it if you want to re-extract the audio."
|
|
return false
|
|
end
|
|
cmd = "ffmpeg -i '#{video_filename}' -vn -acodec copy '#{audio_filename}'"
|
|
IO.popen(cmd) do |io|
|
|
io.each_line do |line|
|
|
puts line
|
|
end
|
|
end
|
|
true
|
|
end
|
|
|
|
def save_video
|
|
IO.popen("youtube-dl #{url}") do |io|
|
|
io.each_line do |line|
|
|
puts line
|
|
|
|
if line =~ /^\[download\] /
|
|
@video_filename =
|
|
if line =~ /Destination:/
|
|
line.split(': ').last
|
|
else
|
|
line.sub('[download] ', '').sub(' has already been downloaded', '')
|
|
end.sub(/[\s\r\n]*$/, '')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
main if $0 == __FILE__
|