Module: Video2gif::FFmpeg
- Includes:
- Subtitles
- Defined in:
- lib/video2gif/ffmpeg.rb,
lib/video2gif/ffmpeg/subtitles.rb
Defined Under Namespace
Modules: Subtitles
Constant Summary
collapse
- CROP_REGEX =
/crop=([0-9]+\:[0-9]+\:[0-9]+\:[0-9]+)/
Constants included
from Subtitles
Subtitles::KNOWN_BITMAP_FORMATS, Subtitles::KNOWN_TEXT_FORMATS
Class Method Summary
collapse
Methods included from Subtitles
included
Class Method Details
.crop(options) ⇒ Object
46
47
48
49
50
51
52
53
54
55
|
# File 'lib/video2gif/ffmpeg.rb', line 46
def self.crop(options)
crop_parameters = []
crop_parameters << "w=#{options[:wregion]}" if options[:wregion]
crop_parameters << "h=#{options[:hregion]}" if options[:hregion]
crop_parameters << "x=#{options[:xoffset]}" if options[:xoffset]
crop_parameters << "y=#{options[:yoffset]}" if options[:yoffset]
'crop=' + crop_parameters.join(':') unless crop_parameters.empty?
end
|
.cropdetect_command(options, logger, executable: 'ffmpeg') ⇒ Object
210
211
212
213
214
215
216
217
218
219
|
# File 'lib/video2gif/ffmpeg.rb', line 210
def self.cropdetect_command(options, logger, executable: 'ffmpeg')
command = ffmpeg_command(options, executable: executable)
command << '-filter_complex' << "cropdetect=limit=#{options[:autocrop]}"
command << '-f' << 'null'
command << '-'
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
command
end
|
.drawtext(options) ⇒ Object
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
# File 'lib/video2gif/ffmpeg.rb', line 124
def self.drawtext(options)
if options[:text]
count_of_lines = options[:text].scan(/\\n/).count + 1
drawtext_parameters = []
drawtext_parameters << "x='#{ options[:xpos] || '(main_w/2-text_w/2)' }'"
drawtext_parameters << "y='#{ options[:ypos] || "(main_h-line_h*1.5*#{count_of_lines})" }'"
drawtext_parameters << "fontsize='#{ options[:textsize] || 32 }'"
drawtext_parameters << "fontcolor='#{ options[:textcolor] || 'white' }'"
drawtext_parameters << "borderw='#{ options[:textborder] || 2 }'"
drawtext_parameters << "fontfile='#{ options[:textfont] || 'Arial'}'\\\\:style='#{options[:textvariant] || 'Bold' }'"
drawtext_parameters << "text='#{text(options)}'"
'drawtext=' + drawtext_parameters.join(':')
end
end
|
.eq(options) ⇒ Object
101
102
103
104
105
106
107
108
109
110
111
112
113
|
# File 'lib/video2gif/ffmpeg.rb', line 101
def self.eq(options)
eq_parameters = []
eq_parameters << "contrast=#{options[:contrast]}" if options[:contrast]
eq_parameters << "brightness=#{options[:brightness]}" if options[:brightness]
eq_parameters << "saturation=#{options[:saturation]}" if options[:saturation]
eq_parameters << "gamma=#{options[:gamma]}" if options[:gamma]
eq_parameters << "gamma_r=#{options[:gamma_r]}" if options[:gamma_r]
eq_parameters << "gamma_g=#{options[:gamma_g]}" if options[:gamma_g]
eq_parameters << "gamma_b=#{options[:gamma_b]}" if options[:gamma_b]
'eq=' + eq_parameters.join(":")
end
|
.ffmpeg_command(options, executable: 'ffmpeg') ⇒ Object
196
197
198
199
200
201
202
203
204
205
206
207
208
|
# File 'lib/video2gif/ffmpeg.rb', line 196
def self.ffmpeg_command(options, executable: 'ffmpeg')
command = [executable]
command << '-y'
command << '-hide_banner'
command << '-loglevel' << 'verbose'
command << '-ss' << options[:seek] if options[:seek]
command << '-t' << options[:time] if options[:time]
command << '-i' << options[:input_filename]
command << '-an'
command << '-sn'
command << '-dn'
end
|
.ffprobe_command(options, logger, executable: 'ffprobe') ⇒ Object
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/video2gif/ffmpeg.rb', line 184
def self.ffprobe_command(options, logger, executable: 'ffprobe')
command = [executable]
command << '-v' << 'error'
command << '-show_entries' << 'stream'
command << '-print_format' << 'json'
command << '-i' << options[:input_filename]
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
command
end
|
.filtergraph(options) ⇒ Object
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
|
# File 'lib/video2gif/ffmpeg.rb', line 164
def self.filtergraph(options)
filtergraph = []
filtergraph << bitmap_subtitles_scale_overlay(options)
filtergraph << rate_with_interpolation(options)
filtergraph << fps(options)
filtergraph << options[:autocrop] if options[:autocrop]
filtergraph << crop(options)
filtergraph << zscale_and_tonemap(options)
filtergraph << scale(options)
filtergraph << eq(options)
filtergraph << text_subtitles(options)
filtergraph << drawtext(options)
filtergraph << split
filtergraph << palettegen(options)
filtergraph << paletteuse(options)
filtergraph.flatten.compact
end
|
.fps(options) ⇒ Object
42
43
44
|
# File 'lib/video2gif/ffmpeg.rb', line 42
def self.fps(options)
"fps=#{ options[:fps] || 20 }"
end
|
.gif_command(options, logger, executable: 'ffmpeg') ⇒ Object
221
222
223
224
225
226
227
228
229
230
|
# File 'lib/video2gif/ffmpeg.rb', line 221
def self.gif_command(options, logger, executable: 'ffmpeg')
command = ffmpeg_command(options, executable: executable)
command << '-filter_complex' << filtergraph(options).join(',')
command << '-f' << 'gif'
command << options[:output_filename]
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
command
end
|
.interpolate(options) ⇒ Object
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/video2gif/ffmpeg.rb', line 20
def self.interpolate(options)
if options[:rate] && Float(options[:rate]) < 1 minterpolate_parameters = []
minterpolate_parameters << 'mi_mode=mci'
minterpolate_parameters << 'mc_mode=aobmc'
minterpolate_parameters << 'me_mode=bidir'
minterpolate_parameters << 'me=epzs'
minterpolate_parameters << 'vsbmc=1'
minterpolate_parameters << "fps=#{video_info(options)[:avg_frame_rate] }/#{options[:rate]}"
'minterpolate=' + minterpolate_parameters.join(':')
end
end
|
.palettegen(options) ⇒ Object
145
146
147
148
149
150
151
152
|
# File 'lib/video2gif/ffmpeg.rb', line 145
def self.palettegen(options)
palettegen_parameters = []
palettegen_parameters << "#{ options[:palette] || 256 }"
palettegen_parameters << "stats_mode=#{options[:palettemode] || 'diff'}"
'[palettegen]palettegen=' + palettegen_parameters.join(':') + '[palette]'
end
|
.paletteuse(options) ⇒ Object
154
155
156
157
158
159
160
161
162
|
# File 'lib/video2gif/ffmpeg.rb', line 154
def self.paletteuse(options)
paletteuse_parameters = []
paletteuse_parameters << "dither=#{options[:dither] || 'floyd_steinberg'}"
paletteuse_parameters << 'diff_mode=rectangle'
paletteuse_parameters << "#{options[:palettemode] == 'single' ? 'new=1' : ''}"
'[paletteuse][palette]paletteuse=' + paletteuse_parameters.join(':')
end
|
.rate(options) ⇒ Object
16
17
18
|
# File 'lib/video2gif/ffmpeg.rb', line 16
def self.rate(options)
"setpts=PTS/#{options[:rate]}" if options[:rate]
end
|
.rate_with_interpolation(options) ⇒ Object
35
36
37
38
39
40
|
# File 'lib/video2gif/ffmpeg.rb', line 35
def self.rate_with_interpolation(options)
[
rate(options),
interpolate(options)
]
end
|
.scale(options) ⇒ Object
88
89
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/video2gif/ffmpeg.rb', line 88
def self.scale(options)
unless options[:tonemap]
scale_parameters = []
scale_parameters << 'flags=lanczos'
scale_parameters << 'sws_dither=none'
scale_parameters << "width=#{ options[:width] || 480 }"
scale_parameters << "height=trunc(#{ options[:width] || 480 }/dar)"
'scale=' + scale_parameters.join(':')
end
end
|
.split ⇒ Object
141
142
143
|
# File 'lib/video2gif/ffmpeg.rb', line 141
def self.split
'split[palettegen][paletteuse]'
end
|
.text(options) ⇒ Object
115
116
117
118
119
120
121
122
|
# File 'lib/video2gif/ffmpeg.rb', line 115
def self.text(options)
options[:text].gsub(/\\n/, '')
.gsub(/([:])/, '\\\\\\\\\\1')
.gsub(/([,])/, '\\\\\\1')
.gsub(/\b'\b/, "\u2019")
.gsub(/\B"\b([^"\u201C\u201D\u201E\u201F\u2033\u2036\r\n]+)\b?"\B/, "\u201C\\1\u201D")
.gsub(/\B'\b([^'\u2018\u2019\u201A\u201B\u2032\u2035\r\n]+)\b?'\B/, "\u2018\\1\u2019")
end
|
.tonemap(options) ⇒ Object
68
69
70
71
72
73
74
75
76
77
|
# File 'lib/video2gif/ffmpeg.rb', line 68
def self.tonemap(options)
%W[
zscale=transfer=linear:npl=100
format=gbrpf32le
zscale=primaries=bt709
tonemap=tonemap=#{options[:tonemap]}:param=1.0:desat=0:peak=10
zscale=transfer=bt709:matrix=bt709:range=tv
format=yuv420p
]
end
|
.video_info(options) ⇒ Object
12
13
14
|
# File 'lib/video2gif/ffmpeg.rb', line 12
def self.video_info(options)
options[:probe_infos][:streams].find { |s| s[:codec_type] == 'video' }
end
|
.zscale(options) ⇒ Object
57
58
59
60
61
62
63
64
65
66
|
# File 'lib/video2gif/ffmpeg.rb', line 57
def self.zscale(options)
zscale_parameters = []
zscale_parameters << 'dither=none'
zscale_parameters << 'filter=lanczos'
zscale_parameters << "width=#{ options[:width] || 480 }"
zscale_parameters << "height=trunc(#{ options[:width] || 480 }/dar)"
'zscale=' + zscale_parameters.join(':')
end
|
.zscale_and_tonemap(options) ⇒ Object
79
80
81
82
83
84
85
86
|
# File 'lib/video2gif/ffmpeg.rb', line 79
def self.zscale_and_tonemap(options)
if options[:tonemap]
[
zscale(options),
tonemap(options)
]
end
end
|