Skip to content

Instantly share code, notes, and snippets.

@oneman
Created October 10, 2012 08:13
Show Gist options
  • Save oneman/3863965 to your computer and use it in GitHub Desktop.
Save oneman/3863965 to your computer and use it in GitHub Desktop.
Multithreaded Recursive FLAC dir -> Opus converter
#!/usr/bin/env ruby
#
# Multithreaded Recursive FLAC dir -> Opus converter
# Destination dir tree is flat
#
# Example:
# flac_to_opus.rb music/ /media/3632-6166/MUSIC/
#
$bitrate = 180
$threads = 5
# you want to use a temp file if writing to a
# sd card to prevent lots of small writes
$usetempfile = true
class FlacToOpus
def initialize(in_filename, out_filename)
@finished = false
@in_filename = in_filename
@out_filename = out_filename
@temp_filename = in_filename + ".opustemp"
if $usetempfile == true
if File.exists?(@out_filename)
@finished = true
end
else
@temp_filename = @out_filename
if File.exists?(@out_filename)
@finished = true
end
end
if @finished == false
puts "Encoding: " + @in_filename + " -> " + @out_filename
@thread = Thread.new { flac_to_opus(@in_filename, @temp_filename) }
end
end
def finish
return true if @finished
@thread.join(0.05)
if @thread.status == false or @thread.status == nil
if $usetempfile == true
`mv "#{@temp_filename}" "#{@out_filename}"`
end
return true
end
return false
end
def is_flac_file(filename)
result = `metaflac --list "#{filename}" 2>&1`
return !result.include?("ERROR")
end
def flac_to_opus(in_filename, out_filename)
return if !is_flac_file(in_filename)
flac_cmd = 'flac -scd "' + in_filename + '"'
opusenc_cmd = "opusenc --quiet --bitrate=" + $bitrate.to_s + " "
artist = `metaflac --show-tag=artist "#{in_filename}"`.chomp.sub("artist=","")
title = `metaflac --show-tag=title "#{in_filename}"`.chomp.sub("title=","")
if artist.length > 0
opusenc_cmd += '--artist="' + artist + '" '
end
if title.length > 0
opusenc_cmd += '--title="' + title + '" '
end
opusenc_cmd += ' - "' + out_filename + '"'
cmd = flac_cmd + ' | ' + opusenc_cmd
`#{cmd}`
end
end
class FlacDirToOpusDir
def initialize(in_dir, out_dir)
@encoders = []
Process.setpriority(Process::PRIO_PROCESS, 0, 15)
flacdir_to_opusdir(in_dir, out_dir)
end
def flacdir_to_opusdir(in_dir, out_dir)
if in_dir[0] != "/"
in_dir = "./" + in_dir
end
if out_dir[0] != "/"
out_dir = "./" + out_dir
end
in_dir = File.absolute_path(in_dir)
out_dir = File.absolute_path(out_dir)
topdirname = File.basename(in_dir)
out_dir_orig = out_dir
out_dir += "/" + topdirname
puts in_dir + ' -> ' + out_dir
Dir.foreach(in_dir) do |filename|
next if filename == '.' or filename == '..' or filename == '-'
if File.extname(filename) == ".flac"
`mkdir -p "#{out_dir}"`
while @encoders.length > $threads - 1
@encoders.delete_if { |en| en.finish }
end
@encoders.push FlacToOpus.new(in_dir + "/" + filename, out_dir + "/" + File.basename(filename, ".flac") + ".opus")
end
if File.directory?(in_dir + "/" + filename)
flacdir_to_opusdir(in_dir + "/" + filename, out_dir_orig)
end
end
end
end
in_dir = ARGV[0]
out_dir = ARGV[1].chomp
if in_dir && out_dir
FlacDirToOpusDir.new(in_dir, out_dir)
else
puts "flac_to_opus [INDIR] [OUTDIR]"
end
@tokyovigilante
Copy link

If you have fd installed, a nice one-liner is:
fd -e flac -x opusenc --bitrate 128 {} {.}.opus

@f35f22fan
Copy link

If you have fd installed, a nice one-liner is:
fd -e flac -x opusenc --bitrate 128 {} {.}.opus

That's impressive!

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