-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathfilter.rb
More file actions
202 lines (178 loc) · 6.1 KB
/
filter.rb
File metadata and controls
202 lines (178 loc) · 6.1 KB
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# frozen_string_literal: true
require_relative 'command_args'
module FFMPEG
# The Filter class represents a ffmpeg filter
# that can be applied to a stream.
#
# @example
# filter = FFMPEG::Filter.new(:video, 'scale', w: -2, h: 720)
# filter.to_s # => "scale=w=-2:h=720"
# filter.with_input_link('0:v').with_output_link('v0').to_s # => "[0:v]scale=w=-2:h=720[v0]"
class Filter
class << self
# Join the filters together into a filter chain
# that can be applied to a stream.
#
# @param filters [Array<Filter>] The filters to join.
# @return [String] The filter chain.
def join(*filters)
filters.compact.join(',')
end
end
attr_reader :type, :name, :kwargs, :input_links, :output_links
# @param type [Symbol] The type of the filter (must be one of :video or :audio).
# @param name [String] The name of the filter (e.g.: 'scale', 'volume').
# @param kwargs [Hash] The keyword arguments to use for the filter.
def initialize(type, name, **kwargs)
raise ArgumentError, "Unknown type #{type}, expected :video or :audio" unless %i[audio video].include?(type)
raise ArgumentError, "Unknown name format #{name.class}, expected #{String}" unless name.is_a?(String)
@type = type
@name = name
kwargs = kwargs.compact
@kwargs = kwargs unless kwargs.empty?
@input_links = []
@output_links = []
end
# Clone the filter.
def clone
super.tap do |filter|
filter.instance_variable_set(:@input_links, @input_links.clone)
filter.instance_variable_set(:@output_links, @output_links.clone)
end
end
# Convert the filter to a string.
#
# @return [String] The filter as a string.
def to_s
[
format_input_links,
[@name, format_kwargs].reject(&:empty?).join('='),
format_output_links
].join
end
# Clone the filter with the specified input links.
#
# @param stream_ids [Array<String>] The stream IDs to use as input links.
# @return [Filter] The cloned filter.
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_input_links('0:a:0').to_s # => "[0:a:0]silencedetect"
def with_input_links(*stream_ids)
clone.with_input_links!(*stream_ids)
end
# Set the specified input links on the filter.
# This will replace any existing input links.
#
# @param stream_ids [Array<String>] The stream IDs to use as input links.
# @return [self]
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_input_links!('0:a:0')
# filter.to_s # => "[0:a:0]silencedetect"
def with_input_links!(*stream_ids)
@input_links = []
stream_ids.each(&method(:with_input_link!))
self
end
# Clone the filter with the specified input link.
# This will add the input link to the existing input links.
#
# @param stream_id [String] The stream ID to use as input link.
# @return [Filter] The cloned filter.
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_input_link('0:a:0').to_s # => "[0:a:0]silencedetect"
def with_input_link(stream_id)
clone.with_input_link!(stream_id)
end
# Add the specified input link to the filter.
#
# @param stream_id [String] The stream ID to use as input link.
# @return [self]
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_input_link!('0:a:0')
# filter.to_s # => "[0:a:0]silencedetect"
def with_input_link!(stream_id)
unless stream_id.is_a?(String)
raise ArgumentError,
"Unknown stream_id format #{stream_id.class}, expected #{String}"
end
@input_links << stream_id
self
end
# Clone the filter with the specified output links.
# This will replace any existing output links.
#
# @param stream_ids [Array<String>] The stream IDs to use as output links.
# @return [Filter] The cloned filter.
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_output_links('a0', 'a1').to_s # => "silencedetect[a0][a1]"
def with_output_links(*stream_ids)
clone.with_output_links!(*stream_ids)
end
# Set the specified output links on the filter.
# This will replace any existing output links.
#
# @param stream_ids [Array<String>] The stream IDs to use as output links.
# @return [self]
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_output_links!('a0', 'a1')
# filter.to_s # => "silencedetect[a0][a1]"
def with_output_links!(*stream_ids)
@output_links = []
stream_ids.each(&method(:with_output_link!))
self
end
# Clone the filter with the specified output link.
# This will add the output link to the existing output links.
#
# @param stream_id [String] The stream ID to use as output link.
# @return [Filter] The cloned filter.
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_output_link('a0').to_s # => "silencedetect[a0]"
def with_output_link(stream_id)
clone.with_output_link!(stream_id)
end
# Add the specified output link to the filter.
#
# @param stream_id [String] The stream ID to use as output link.
# @return [self]
#
# @example
# filter = FFMPEG::Filter.new(:audio, 'silencedetect')
# filter.with_output_link!('a0')
# filter.to_s # => "silencedetect[a0]"
def with_output_link!(stream_id)
unless stream_id.is_a?(String)
raise ArgumentError,
"Unknown stream_id format #{stream_id.class}, expected #{String}"
end
@output_links << stream_id
self
end
protected
def format_kwargs(kwargs = @kwargs)
CommandArgs.format_kwargs(kwargs)
end
def format_input_links
format_links(@input_links)
end
def format_output_links
format_links(@output_links)
end
def format_links(links)
links.map { |link| "[#{link}]" }.join
end
end
end