lib/scissor/chunk.rb in youpy-scissor-0.0.16 vs lib/scissor/chunk.rb in youpy-scissor-0.0.17
- old
+ new
@@ -1,25 +1,30 @@
require 'digest/md5'
require 'pathname'
require 'open4'
require 'logger'
+require 'bigdecimal'
module Scissor
class Chunk
+ @logger = Logger.new(STDOUT)
+ @logger.level = Logger::INFO
+
+ class << self
+ attr_accessor :logger
+ end
+
class Error < StandardError; end
class FileExists < Error; end
class EmptyFragment < Error; end
class OutOfDuration < Error; end
class CommandFailed < Error; end
attr_reader :fragments
- attr_accessor :logger
def initialize(filename = nil)
@fragments = []
- @logger = Logger.new(STDOUT)
- @logger.level = Logger::INFO
if filename
@fragments << Fragment.new(
filename,
0,
@@ -29,16 +34,23 @@
def add_fragment(fragment)
@fragments << fragment
end
- def duration
- @fragments.inject(0) do |memo, fragment|
- memo += fragment.duration
+ def add_fragments(fragments)
+ fragments.each do |fragment|
+ add_fragment(fragment)
end
end
+ def duration
+ BigDecimal(
+ @fragments.inject(0) do |memo, fragment|
+ memo += fragment.duration
+ end.to_s).round(3).to_f
+ end
+
def slice(start, length)
if start + length > duration
raise OutOfDuration
end
@@ -63,36 +75,28 @@
end
alias [] slice
def concat(other)
- other.fragments.each do |fragment|
- add_fragment(fragment)
- end
+ add_fragments(other.fragments)
self
end
alias << concat
def +(other)
new_instance = Scissor()
-
- (@fragments + other.fragments).each do |fragment|
- new_instance.add_fragment(fragment)
- end
-
+ new_instance.add_fragments(@fragments + other.fragments)
new_instance
end
def loop(count)
orig_fragments = @fragments.clone
(count - 1).times do
- orig_fragments.each do |fragment|
- add_fragment(fragment)
- end
+ add_fragments(orig_fragments)
end
self
end
@@ -131,24 +135,24 @@
end
new_instance
end
- def replace(start, duration, replaced)
+ def replace(start, length, replaced)
new_instance = self.class.new
- offset = start + duration
+ offset = start + length
- if offset > self.duration
+ if offset > duration
raise OutOfDuration
end
if start > 0
new_instance += slice(0, start)
end
new_instance += replaced
- new_instance += slice(offset, self.duration - offset)
+ new_instance += slice(offset, duration - offset)
new_instance
end
def reverse
@@ -195,40 +199,41 @@
tmpfile = tmpdir + 'tmp.wav'
cmd = %w/ecasound/
begin
@fragments.each_with_index do |fragment, index|
+ fragment_filename = fragment.filename
+ fragment_duration = fragment.duration
+
if !index.zero? && (index % 80).zero?
run_command(cmd.join(' '))
cmd = %w/ecasound/
end
fragment_tmpfile =
- fragment.filename.extname.downcase == '.wav' ? fragment.filename :
- tmpdir + (Digest::MD5.hexdigest(fragment.filename) + '.wav')
+ fragment_filename.extname.downcase == '.wav' ? fragment_filename :
+ tmpdir + (Digest::MD5.hexdigest(fragment_filename) + '.wav')
unless fragment_tmpfile.exist?
- run_command("ffmpeg -i \"#{fragment.filename}\" \"#{fragment_tmpfile}\"")
+ run_command("ffmpeg -i \"#{fragment_filename}\" \"#{fragment_tmpfile}\"")
end
cmd <<
"-a:#{index} " +
"-i:" +
(fragment.reversed? ? 'reverse,' : '') +
- "select,#{fragment.start},#{fragment.duration},\"#{fragment_tmpfile}\" " +
+ "select,#{fragment.start},#{fragment_duration},\"#{fragment_tmpfile}\" " +
"-o:#{tmpfile} " +
"-y:#{position}"
- position += fragment.duration
+ position += fragment_duration
end
run_command(cmd.join(' '))
if filename.extname == '.wav'
- open(filename, 'w') do |file|
- file.write(tmpfile.read)
- end
+ File.rename(tmpfile, filename)
else
run_command("ffmpeg -i \"#{tmpfile}\" \"#{filename}\"")
end
ensure
tmpdir.rmtree
@@ -246,21 +251,25 @@
def which(command)
run_command("which #{command}")
end
def run_command(cmd)
- @logger.debug("run_command: #{cmd}")
+ logger.debug("run_command: #{cmd}")
result = ''
status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
- @logger.debug(stderr.read)
+ logger.debug(stderr.read)
result = stdout.read
end
if status.exitstatus != 0
raise CommandFailed.new(cmd)
end
return result
+ end
+
+ def logger
+ self.class.logger
end
end
end