Created
October 10, 2012 08:13
-
-
Save oneman/3863965 to your computer and use it in GitHub Desktop.
Multithreaded Recursive FLAC dir -> Opus converter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
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
If you have fd installed, a nice one-liner is:
fd -e flac -x opusenc --bitrate 128 {} {.}.opus