154 lines
4.4 KiB
Ruby
154 lines
4.4 KiB
Ruby
require 'json'
|
|
require 'resque'
|
|
require 'resque-retry'
|
|
require 'net/http'
|
|
require 'digest/md5'
|
|
|
|
module JamRuby
|
|
|
|
# executes a mix of tracks, creating a final output mix
|
|
class QuickMixer
|
|
extend JamRuby::ResqueStats
|
|
|
|
@queue = :quick_mixer
|
|
|
|
@@log = Logging.logger[QuickMixer]
|
|
|
|
attr_accessor :quick_mix_id, :quick_mix, :output_filename, :error_out_filename,
|
|
:postback_mp3_url, :error_reason, :error_detail
|
|
|
|
def self.perform(quick_mix_id, postback_mp3_url)
|
|
|
|
audiomixer = QuickMixer.new
|
|
audiomixer.postback_mp3_url = postback_mp3_url
|
|
audiomixer.quick_mix_id = quick_mix_id
|
|
audiomixer.run
|
|
|
|
end
|
|
|
|
def self.find_jobs_needing_retry &blk
|
|
QuickMix.find_each(:conditions => "completed = FALSE AND (should_retry = TRUE OR (started_at IS NOT NULL AND NOW() - started_at > '1 hour'::INTERVAL))", :batch_size => 100) do |mix|
|
|
blk.call(mix)
|
|
end
|
|
end
|
|
|
|
def self.queue_jobs_needing_retry
|
|
find_jobs_needing_retry do |mix|
|
|
mix.enqueue
|
|
end
|
|
end
|
|
|
|
def initialize
|
|
@s3_manager = S3Manager.new(APP_CONFIG.aws_bucket, APP_CONFIG.aws_access_key_id, APP_CONFIG.aws_secret_access_key)
|
|
end
|
|
|
|
def run
|
|
@@log.info("quickmixer job starting. quick_mix_id #{quick_mix_id}")
|
|
|
|
@quick_mix = QuickMix.find(quick_mix_id)
|
|
|
|
begin
|
|
# bailout check
|
|
if @quick_mix.completed
|
|
@@log.debug("quick mix is already completed. bailing")
|
|
return
|
|
end
|
|
|
|
fetch_audio_files
|
|
|
|
create_mp3(@input_ogg_filename, @output_mp3_filename)
|
|
|
|
postback
|
|
|
|
post_success(@quick_mix)
|
|
|
|
cleanup_files
|
|
|
|
@@log.info("quickmixer job successful. mix_id #{quick_mix_id}")
|
|
|
|
rescue Exception => e
|
|
post_error(@quick_mix, e)
|
|
raise
|
|
end
|
|
end
|
|
|
|
|
|
def postback
|
|
|
|
@@log.debug("posting mp3 mix to #{@postback_mp3_url}")
|
|
|
|
uri = URI.parse(@postback_mp3_url)
|
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
http.use_ssl = @postback_mp3_url.start_with?('https') ? true : false
|
|
request = Net::HTTP::Put.new(uri.request_uri)
|
|
|
|
response = nil
|
|
File.open(@output_mp3_filename,"r") do |f|
|
|
request.body_stream=f
|
|
request["Content-Type"] = "audio/mpeg"
|
|
request.add_field('Content-Length', File.size(@output_mp3_filename))
|
|
response = http.request(request)
|
|
end
|
|
|
|
response_code = response.code.to_i
|
|
unless response_code >= 200 && response_code <= 299
|
|
@error_reason = "postback-mp3-mix-to-s3"
|
|
raise "unable to put to url: #{@postback_mp3_url}, status: #{response.code}, body: #{response.body}"
|
|
end
|
|
|
|
end
|
|
|
|
def post_success(mix)
|
|
|
|
mp3_length = File.size(@output_mp3_filename)
|
|
mp3_md5 = Digest::MD5.new
|
|
File.open(@output_mp3_filename, 'rb').each {|line| mp3_md5.update(line)}
|
|
|
|
mix.finish(mp3_length, mp3_md5.to_s)
|
|
end
|
|
|
|
def post_error(mix, e)
|
|
begin
|
|
|
|
# if error_reason is null, assume this is an unhandled error
|
|
unless @error_reason
|
|
@error_reason = "unhandled-job-exception"
|
|
@error_detail = e.to_s
|
|
end
|
|
mix.errored(error_reason, error_detail)
|
|
|
|
rescue Exception => e
|
|
@@log.error "unable to post back to the database the error #{e}"
|
|
end
|
|
end
|
|
|
|
def cleanup_files()
|
|
File.delete(@input_ogg_filename) if File.exists?(@input_ogg_filename)
|
|
File.delete(@output_mp3_filename) if File.exists?(@output_mp3_filename)
|
|
end
|
|
|
|
|
|
def fetch_audio_files
|
|
@input_ogg_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/quick_mixer_#{@quick_mix.id}}", '.' + @quick_mix.default_type], nil)
|
|
@output_mp3_filename = Dir::Tmpname.make_tmpname( ["#{Dir.tmpdir}/quick_mixer_#{@quick_mix.id}}", '.mp3'], nil)
|
|
@s3_manager.download(@quick_mix[:ogg_url], @input_ogg_filename)
|
|
end
|
|
|
|
private
|
|
|
|
def create_mp3(input_ogg_filename, output_mp3_filename)
|
|
ffmpeg_cmd = "#{APP_CONFIG.ffmpeg_path} -i \"#{input_ogg_filename}\" -ab 128k -metadata JamRecordingId=#{@quick_mix.recording_id} -metadata JamQuickMixId=#{@quick_mix_id} -metadata JamType=QuickMix \"#{output_mp3_filename}\""
|
|
|
|
system(ffmpeg_cmd)
|
|
|
|
unless $? == 0
|
|
@error_reason = 'ffmpeg-failed'
|
|
@error_detail = $?.to_s
|
|
error_msg = "ffmpeg failed status=#{$?} error_reason=#{@error_reason} error_detail=#{@error_detail}"
|
|
@@log.info(error_msg)
|
|
raise error_msg
|
|
end
|
|
|
|
end
|
|
end
|
|
end |