2014-10-23 04:10:49 +00:00
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
2014-12-30 23:10:16 +00:00
extend JamRuby :: ResqueStats
2014-10-23 04:10:49 +00:00
@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 )
2015-01-01 02:39:22 +00:00
audiomixer = QuickMixer . new
audiomixer . postback_mp3_url = postback_mp3_url
audiomixer . quick_mix_id = quick_mix_id
audiomixer . run
2014-10-23 04:10:49 +00:00
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 )
2014-10-27 22:52:56 +00:00
cleanup_files
2014-11-07 22:12:36 +00:00
@@log . info ( " quickmixer job successful. mix_id #{ quick_mix_id } " )
2014-10-23 04:10:49 +00:00
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 )
2015-05-11 21:52:58 +00:00
http . use_ssl = @postback_mp3_url . start_with? ( 'https' ) ? true : false
2014-10-23 04:10:49 +00:00
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
2014-10-27 22:52:56 +00:00
def cleanup_files ( )
2014-11-02 02:10:12 +00:00
File . delete ( @input_ogg_filename ) if File . exists? ( @input_ogg_filename )
File . delete ( @output_mp3_filename ) if File . exists? ( @output_mp3_filename )
2014-10-27 22:52:56 +00:00
end
2014-10-23 04:10:49 +00:00
def fetch_audio_files
@input_ogg_filename = Dir :: Tmpname . make_tmpname ( [ " #{ Dir . tmpdir } /quick_mixer_ #{ @quick_mix . id } } " , '.ogg' ] , 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