/
writer.rb
114 lines (89 loc) · 2.58 KB
/
writer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
require 'open4'
require 'temp_dir'
module Scissor
class Writer
include Loggable
class Error < StandardError; end
class FileExists < Error; end
class EmptyFragment < Error; end
class CommandFailed < Error; end
def initialize
@tracks = []
end
def add_fragments(fragments)
@tracks << fragments
end
def to_file(filename, options)
filename = Pathname.new(filename)
if @tracks.flatten.empty?
raise EmptyFragment
end
which('ecasound')
which('ffmpeg')
options = {
:overwrite => false
}.merge(options)
filename = Pathname.new(filename)
if filename.exist?
if options[:overwrite]
filename.unlink
else
raise FileExists
end
end
TempDir.create do |dir|
tmpdir = Pathname.new(dir)
tmpfile = tmpdir + 'tmp.wav'
cmd = %w/ecasound/
index = 0
@tracks.each do |fragments|
position = 0.0
fragments.each do |fragment|
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')
unless fragment_tmpfile.exist?
run_command("ffmpeg -i \"#{fragment_filename}\" \"#{fragment_tmpfile}\"")
end
cmd <<
"-a:#{index} " +
"-i:" +
(fragment.reversed? ? 'reverse,' : '') +
"select,#{fragment.start},#{fragment_duration},\"#{fragment_tmpfile}\" " +
"-o:#{tmpfile} " +
"-y:#{position}"
index += 1
position += fragment_duration
end
end
run_command(cmd.join(' '))
if filename.extname == '.wav'
File.rename(tmpfile, filename)
else
run_command("ffmpeg -i \"#{tmpfile}\" \"#{filename}\"")
end
end
end
def which(command)
run_command("which #{command}")
end
def run_command(cmd)
logger.debug("run_command: #{cmd}")
result = ''
status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
logger.debug(stderr.read)
result = stdout.read
end
if status.exitstatus != 0
raise CommandFailed.new(cmd)
end
return result
end
end
end