Skip to content

Commit

Permalink
Media file caching and modification
Browse files Browse the repository at this point in the history
Added configuration for paths to stored files.
Added routes for media files.
Added logging to audio module and implementation of wavpack (.wv to .wav
with segmenting).
  • Loading branch information
Mark committed Oct 25, 2012
1 parent c48e15e commit 84c3542
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 25 deletions.
33 changes: 28 additions & 5 deletions app/controllers/media_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,24 @@
class MediaController < ApplicationController
include Spectrogram
include Cache, Spectrogram, Audio

def index
# index page for media files
@testing = QubarSite::Application.config.media_file_config
end

def item
# page for an individual media file
# use params to get query string or parsed route parameters

# get the path for the file matching the request
@file_path = Cache::calculate_target_path(params)

# see if the requested file exists

@avail_params = params

end

def info
@input_path = './test/fixtures/'
# not-an-audio-file.wav
Expand All @@ -12,18 +31,22 @@ def info
@result = Audio::info(@input_audio)
end
def audio
print params

@input_path = './test/fixtures/'
@output_path = './public/tests/'

@audio = 'TorresianCrow.wav'
@modified_audio = 'TorresianCrow.wav'
@audio = 'TestAudio1.wv'
@modified_audio = 'TestAudio1.wav'

@input_audio = @input_path + @audio
@output_audio = @output_path + @modified_audio

@result = Audio::modify(@input_audio, @output_audio, [])

#@result = Audio::modify(@input_audio, @output_audio, [])
end
def spectrogram
print params
@input_path = './test/fixtures/'
@output_path = './public/tests/'

Expand All @@ -33,6 +56,6 @@ def spectrogram
@input_audio = @input_path + @audio
@output_image = @output_path + @image

@result = Spectrogram::generate(@input_audio, @output_image)
#@result = Spectrogram::generate(@input_audio, @output_image)
end
end
Empty file removed app/views/media/audio.html.erb
Empty file.
3 changes: 3 additions & 0 deletions app/views/media/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>Media#index</h1>
<p>Index page for media controller.</p>
<p><%= @testing %></p>
1 change: 0 additions & 1 deletion app/views/media/info.html.erb

This file was deleted.

4 changes: 4 additions & 0 deletions app/views/media/item.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<h1>Media#item</h1>
<p>Individual item page for media controller.</p>
<p><%= @avail_params %></p>
<p><%= @file_path %></p>
3 changes: 0 additions & 3 deletions app/views/media/spectrogram.html.erb

This file was deleted.

1 change: 1 addition & 0 deletions lib/modules/OS.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# From http://stackoverflow.com/questions/170956/how-can-i-find-which-operating-system-my-ruby-program-is-running-on
module OS
def OS.windows?
(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
Expand Down
58 changes: 44 additions & 14 deletions lib/modules/audio.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
require 'OS'

module Audio

@ffmpeg_path = "./vendor/bin/ffmpeg/windows/ffmpeg.exe"
@ffprobe_path = "./vendor/bin/ffmpeg/windows/ffprobe.exe"
@sox_path = "./vendor/bin/sox/windows/sox.exe"
@wvunpack_path = "./vendor/bin/wavpack/windows/wvunpack.exe"
@mp3splt_path = "./vendor/bin/mp3splt/windows/mp3splt.exe"
@ffmpeg_path = if OS.windows? then "./vendor/bin/ffmpeg/windows/ffmpeg.exe" else "ffmpeg" end
@ffprobe_path = if OS.windows? then "./vendor/bin/ffmpeg/windows/ffprobe.exe" else "ffprobe" end
@sox_path = if OS.windows? then "./vendor/bin/sox/windows/sox.exe" else "sox" end
@wvunpack_path = if OS.windows? then "./vendor/bin/wavpack/windows/wvunpack.exe" else "wvunpack" end
@mp3splt_path = if OS.windows? then "./vendor/bin/mp3splt/windows/mp3splt.exe" else "mp3splt" end

@@my_logger ||= Logger.new("#{Rails.root}/log/my.log")

Expand All @@ -28,14 +30,7 @@ def self.info(source)
# Creates a new audio file from source path in target path, modified according to the
# parameters in modify_parameters
def self.modify(source, target, modify_parameters)
# sox command to create a spectrogram from an audio file
command = "#{@sox_path} #{@sox_arguments_verbose} \"#{source}\" #{@sox_arguments_output_audio} #{@sox_arguments_sample_rate} #{@sox_arguments_spectrogram} #{@sox_arguments_output} \"#{target}\""

# run the command and wait for the result
stdout_str, stderr_str, status = Open3.capture3(command)

# package up all the available information and return it
result = [ stdout_str, stderr_str, status, File.exist?(source), File.exist?(target) ]
wvunpack(source, target, modify_parameters)
end

# private methods
Expand All @@ -51,6 +46,7 @@ def self.sox_info(source, info, error)
sox_stdout_str.strip.split(/\r?\n|\r/).each { |line| info.push [ 'SOX ' + line[0,line.index(':')].strip, line[line.index(':')+1,line.length].strip ] }
# sox_stderr_str is empty
else
Rails.logger.debug "Sox info error. Return status #{sox_status.exitstatus}. Command: #{sox_command}"
error.push ['SOX ERROR',sox_stderr_str]
end
end
Expand All @@ -60,6 +56,8 @@ def self.ffprobe_info(source, info, error)
ffprobe_command = "#{@ffprobe_path} #{ffprobe_arguments_info} \"#{source}\""
ffprobe_stdout_str, ffprobe_stderr_str, ffprobe_status = Open3.capture3(ffprobe_command)

Rails.logger.debug "Ffprobe info return status #{ffprobe_status.exitstatus}. Command: #{ffprobe_command}"

if ffprobe_status.exitstatus == 0
# ffprobe std out contains info (separate on first equals(=))
# ffprobe_stderr_str contains progress info and human-formatted info
Expand All @@ -76,6 +74,7 @@ def self.ffprobe_info(source, info, error)
end
end
else
Rails.logger.debug "Ffprobe info error. Return status #{ffprobe_status.exitstatus}. Command: #{ffprobe_command}"
# ffprobe std err contains info (separate on first equals(=))
ffprobe_current_block_name = ''
ffprobe_stdout_str.strip.split(/\r?\n|\r/).each do |line|
Expand All @@ -96,7 +95,9 @@ def self.wvunpack_info(source, info, error)
wvunpack_arguments_info = "-s"
wvunpack_command = "#{@wvunpack_path} #{wvunpack_arguments_info} \"#{source}\"" # commands to get info from audio file
wvunpack_stdout_str, wvunpack_stderr_str, wvunpack_status = Open3.capture3(wvunpack_command) # run the commands and wait for the result


Rails.logger.debug "Wavpack info return status #{wvunpack_status.exitstatus}. Command: #{wvunpack_command}"

if wvunpack_status.exitstatus == 0
# wvunpack std out contains info (separate on first colon(:))
wvunpack_stdout_str.strip.split(/\r?\n|\r/).each do |line|
Expand All @@ -112,4 +113,33 @@ def self.wvunpack_info(source, info, error)
end
end

# wvunpack converts .wv files to .wav, optionally segmenting them
# target should be calculated based on modify_parameters by cache module
# modify_parameters can contain start_offset (fractions of seconds from start) and/or end_offset (fractions of seconds from start)
def self.wvunpack(source, target, modify_parameters = {})
raise ArgumentError, "Source is not a wavpack file: #{File.basename(source)}" unless source.match(/\.wv$/)
raise ArgumentError, "Target is not a wav file: : #{File.basename(target)}" unless target.match(/\.wav$/)
raise ArgumentError, "Source does not exist: #{File.basename(source)}" unless File.exists? source
raise ArgumentError, "Target exists: #{File.basename(target)}" unless !File.exists? source

# formatted time: hh:mm:ss.ss
arguments = '-t -q'
if modify_parameters.include? :start_offset
start_offset_formatted = Time.at(modify_parameters[:start_offset]).utc.strftime('%H:%M:%S.%2N')
arguments += ' --skip=#{start_offset_formatted}'
end

if modify_parameters.include? :end_offset
end_offset_formatted = Time.at(modify_parameters[:start_offset]).utc.strftime('%H:%M:%S.%2N')
arguments += ' --until=#{end_offset_formatted}'
end

wvunpack_command = "#{@wvunpack_path} #{arguments} \"#{source}\" \"#{target}\"" # commands to get info from audio file
wvunpack_stdout_str, wvunpack_stderr_str, wvunpack_status = Open3.capture3(wvunpack_command) # run the commands and wait for the result

if wvunpack_status.exitstatus == 0
raise "Wvunpack exited with an error: #{wvunpack_stderr_str}"
end
end

end
17 changes: 17 additions & 0 deletions lib/modules/cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module Cache

public

# calculate the target file name and path based on the modification parameters
def self.calculate_target_path(modify_parameters = {})
#Mime::Type.lookup_by_extension(
#QubarSite::Application.config.media_file_config
end

# check to see if a target file exists
def self.exists(source, modify_parameters = {})
File.exists? calculate_target_path(source, modify_parameters)
end

private
end
4 changes: 2 additions & 2 deletions lib/modules/spectrogram.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module Spectrogram
@sox_arguments_sample_rate = "rate 22050"
@sox_arguments_spectrogram = "spectrogram -m -r -l -a -q 249 -w hann -y 257 -X 43.06640625 -z 100"
@sox_arguments_output = "-o"
@my_logger ||= Logger.new("#{Rails.root}/log/my.log")

# Generate a spectrogram image from an audio file.
# The spectrogram will be 257 pixels high, but the length is not known exactly beforehand.
Expand All @@ -18,6 +17,7 @@ def self.generate(source, target)

# check for existing image, and do not overwrite
if File.exist?(target)
Rails.logger.warn "Target path for spectrogram generation already exists: #{target}."
return [ "", "", "", source, File.exist?(source), target, File.exist?(target) ]
end

Expand All @@ -28,7 +28,7 @@ def self.generate(source, target)
stdout_str, stderr_str, status = Open3.capture3(command)

# log the command
@my_logger.debug(command)
Rails.logger.debug "Spectrogram generation return status #{status.exitstatus}. Command: #{command}"

# package up all the available information and return it
result = [ stdout_str, stderr_str, status, source, File.exist?(source), target, File.exist?(target) ]
Expand Down
5 changes: 5 additions & 0 deletions lib/modules/string.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class String
def trim(replace_chars, substitute_chars)
"#{self}".gsub(/^[#{substitute_chars}]+|[#{substitute_chars}]+$/, replace_chars)
end
end
Binary file added public/tests/TestAudio1.wav
Binary file not shown.
1 change: 1 addition & 0 deletions vendor/bin/install_console_audio_tools.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sudo apt-get install ffmpeg=4:0.8.3-0ubuntu0.12.04.1 mp3splt=2.4.1-0ubuntu1 sox=14.3.2-3 wavpack=4.60.1-2

0 comments on commit 84c3542

Please sign in to comment.