Skip to content

Instantly share code, notes, and snippets.

@riyad
Last active November 17, 2018 22:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riyad/4722364 to your computer and use it in GitHub Desktop.
Save riyad/4722364 to your computer and use it in GitHub Desktop.
Small scripts to transcode any file VLC or ffmpeg can play to mp3.
#!/usr/bin/env ruby -rubygems
#
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de>
# License: Mozilla Public License 2.0
#
# Transcode any file ffmpeg can play to mp3.
require 'optparse'
require 'shellwords'
#
# helpers
#
def puts_error(message)
puts "Error: #{message}"
end
def puts_warning(message)
puts "Warning: #{message}"
end
#
# parse options
#
options = {
:bit_rate => 192,
}
begin
OptionParser.new do |opts|
opts.banner = "Usage: convert2mp3 [options] FILE [<FILE ...>]"
opts.separator ""
opts.separator "Conversion Options:"
opts.on("-f", "--[no-]force", "Overwrite mp3 file if it exists already") do |f|
options[:force_overwrite] = f
end
opts.on("-o", "--output-directoy [DIRECTORY]", "Save converted files to this directory") do |out_dir|
unless File.directory?(out_dir)
puts_error %Q(Wrong output directory. "#{out_dir}" is not a directory.)
exit 1
end
options[:output_dir] = out_dir
end
opts.separator ""
opts.separator "mp3 Options:"
opts.on("-b", "--bit-rate [RATE]", Integer, "Bit rate in kbit/s (default: #{options[:bit_rate]})") do |b|
options[:bit_rate] = b
end
opts.separator ""
opts.separator "General Options:"
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit 0
end
opts.on_tail("-v", "--[no-]verbose", "Be more verbose") do |v|
options[:verbose] = v
end
end.parse!
rescue OptionParser::InvalidOption => e
puts_error e.message
exit 1
end
#
# gather source files
#
if ARGV.empty?
puts_error "No files given."
exit 1
end
source_files = []
while !ARGV.empty?
source_path = ARGV.shift
unless File.exists?(source_path)
puts_warning %Q(Skipping "#{source_path}". It doesn't exist.)
next
end
unless File.file?(source_path)
puts_warning %Q(Skipping "#{source_path}". It's not a file.)
next
end
source_files << source_path
end
#
# ffmpeg command line options
#
FFMPEG = 'ffmpeg'
TRANSCODING = '-vn -ab BIT_RATEk -vbr on -f mp3'.
gsub('BIT_RATE', options[:bit_rate].to_s)
VERBOSITY = options[:verbose] ? '-v info' : '-v quiet'
if `which #{FFMPEG} > /dev/null` && $? != 0
puts_error "Couldn't find ffmpeg."
exit 1
end
source_files.each do |source_file|
source_dir = File.dirname(source_file)
output_dir = options[:output_dir] || source_dir
output_file = File.join(output_dir, "#{File.basename(source_file, ".*")}.mp3")
if File.exist?(output_file)
if options[:force_overwrite]
puts_warning %Q(Output file exists. "#{output_file}" will be overwritten.) if options[:verbose]
else
puts_warning %Q(Output file exists already. Skipping "#{output_file}".)
next
end
end
puts %Q(Converting "#{source_file}")
unless system("#{FFMPEG} #{VERBOSITY} -y -i #{source_file.shellescape} #{TRANSCODING} #{output_file.shellescape}")
puts_error "Conversion failed. Try using the -v option for more detailed output."
end
puts if options[:verbose]
end
#!/usr/bin/env ruby -rubygems
#
# Author: Riyad Preukschas <riyad@informatik.uni-bremen.de>
# License: Mozilla Public License 2.0
#
# Transcode any file VLC can play to mp3.
require 'optparse'
require 'mkmf'
require 'shellwords'
#
# helpers
#
def puts_error(message)
puts "Error: #{message}"
end
def puts_warning(message)
puts "Warning: #{message}"
end
#
# parse options
#
options = {
:bit_rate => 192,
:sampling_rate => 44100,
}
begin
OptionParser.new do |opts|
opts.banner = "Usage: convert2mp3 [options] FILE [<FILE ...>]"
opts.separator ""
opts.separator "Conversion Options:"
opts.on("-f", "--[no-]force", "Overwrite mp3 file if it exists already") do |f|
options[:force_overwrite] = f
end
opts.on("-o", "--output-directoy [DIRECTORY]", "Save converted files to this directory") do |out_dir|
unless File.directory?(out_dir)
puts_error %Q(Wrong output directory. "#{out_dir}" is not a directory.)
exit 1
end
options[:output_dir] = out_dir
end
opts.separator ""
opts.separator "mp3 Options:"
opts.on("-b", "--bit-rate [RATE]", Integer, "Bit rate in kbit/s (default: #{options[:bit_rate]})") do |b|
options[:bit_rate] = b
end
opts.on("-s", "--sampling-rate [RATE]", Integer, "Sampling rate in Hz (default: #{options[:sampling_rate]})") do |s|
options[:sampling_rate] = s
end
opts.separator ""
opts.separator "General Options:"
opts.on_tail("-h", "--help", "Show this message") do
puts opts
exit 0
end
opts.on_tail("-v", "--[no-]verbose", "Be more verbose") do |v|
options[:verbose] = v
end
end.parse!
rescue OptionParser::InvalidOption => e
puts_error e.message
exit 1
end
#
# gather source files
#
if ARGV.empty?
puts_error "No files given."
exit 1
end
source_files = []
while !ARGV.empty?
source_path = ARGV.shift
unless File.exists?(source_path)
puts_warning %Q(Skipping "#{source_path}". It doesn't exist.)
next
end
unless File.file?(source_path)
puts_warning %Q(Skipping "#{source_path}". It's not a file.)
next
end
source_files << source_path
end
#
# VLC command line options
#
# using find_executable() will create a mkmf.log file :(
vlc_paths = [
'vlc',
'/Applications/VLC.app/Contents/MacOS/VLC',
File.expand_path('~/Applications/VLC.app/Contents/MacOS/VLC'),
]
VLC = vlc_paths.find { |path| find_executable0(path) }
INTERFACE = '-I dummy'
PLAYBACK = '--no-loop --no-repeat --play-and-exit'
TRANSCODING = '--sout="#transcode{vcodec=dummy,acodec=mp3,ab=BIT_RATE,channels=2,samplerate=SAMPLING_RATE}:standard{access=file,mux=raw,dst=\'DESTINATION\'}"'.
gsub('BIT_RATE', options[:bit_rate].to_s).
gsub('SAMPLING_RATE', options[:sampling_rate].to_s)
VERBOSITY = options[:verbose] ? '' : '-q 2>/dev/null 1>/dev/null'
if VLC.nil?
puts_error "Couldn't find VLC."
exit 1
end
source_files.each do |source_file|
source_dir = File.dirname(source_file)
output_dir = options[:output_dir] || source_dir
output_file = File.join(output_dir, "#{File.basename(source_file, ".*")}.mp3")
if File.exist?(output_file)
if options[:force_overwrite]
puts_warning %Q(Output file exists. "#{output_file}" will be overwritten.) if options[:verbose]
else
puts_warning %Q(Output file exists already. Skipping "#{output_file}".)
next
end
end
puts %Q(Converting "#{source_file}")
unless system("#{VLC} #{PLAYBACK} #{INTERFACE} #{TRANSCODING.gsub('DESTINATION', output_file.gsub(/'/, ""))} #{source_file.shellescape} #{VERBOSITY}")
puts_error "Conversion failed. Try using the -v option for more detailed output."
end
puts if options[:verbose]
end
@riyad
Copy link
Author

riyad commented Feb 6, 2013

Caveat: in its current form it only works and has been tested on OS X. 😥
Thanks to Kris Hom for the inspiration. 😄

@riyad
Copy link
Author

riyad commented Mar 1, 2014

Update:

  • Check whether VLC is installed
  • Should also work on Linux now
  • Increase default bit rate to 192kbit/s
  • Fixed bug where the file/playlist would repeat endlessly

@riyad
Copy link
Author

riyad commented Nov 5, 2014

Update:

  • Also look for VLC in ~/Application/

@riyad
Copy link
Author

riyad commented Mar 5, 2016

Update:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment