video2gif 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -7
- data/lib/video2gif.rb +40 -72
- data/lib/video2gif/version.rb +1 -1
- data/video2gif.gemspec +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9033455c4d54099067dd61428f3190e75bc52783ab0ee110effa5cb9efedf688
|
4
|
+
data.tar.gz: fd1092a4ef5ffa4c280861fa084444ed2d3b260139062488824c71c3de0957ee
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19a4bfdfb4abd9f13c9c0b8f6a558ef9c1563c620c864e70b3ed96f59b2dd344e153c7900561b92298b18fdc3094ea8a8feb7f4fc2d1f67b2ba90adbc95f757a
|
7
|
+
data.tar.gz: f7c4f43908ca23a75651a73c3cff2cd30407024296ad3fab227f6dba331d0276228e54032458cf7d80739c0b6b4bd8f440508ef101ce5d6edd788e9f0d680084
|
data/README.md
CHANGED
@@ -3,10 +3,10 @@ video2gif
|
|
3
3
|
|
4
4
|
`video2gif` eases converting any video into a GIF.
|
5
5
|
|
6
|
-
It uses [FFMpeg]
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
It uses [FFMpeg], so it understands any video that [FFMpeg] does. It has
|
7
|
+
an array of options to allow you to select the part of the video you
|
8
|
+
want, crop it automatically, overlay text, and manipulate the color and
|
9
|
+
brightness.
|
10
10
|
|
11
11
|
|
12
12
|
Installation
|
@@ -17,9 +17,6 @@ available in the system `$PATH`. If you can run `ffmpeg` from the
|
|
17
17
|
command line, you're probably good. If not, use your favorite package
|
18
18
|
manager to install it.
|
19
19
|
|
20
|
-
If you install [ImageMagick], further optimization will automatically
|
21
|
-
take place on the resulting GIF.
|
22
|
-
|
23
20
|
Note that some features may not be available by default. For example,
|
24
21
|
tonemapping (used for HDR videos) requires `libzimg` support, not
|
25
22
|
included by default in the [FFMpeg] supplied by [Homebrew].
|
data/lib/video2gif.rb
CHANGED
@@ -93,12 +93,6 @@ module Video2gif
|
|
93
93
|
options[:cropdetect] = c || 24
|
94
94
|
end
|
95
95
|
|
96
|
-
parser.on('-o',
|
97
|
-
'--[no-]optimize',
|
98
|
-
'Attempt to optimize GIF size with ImageMagick (default yes if available)') do |o|
|
99
|
-
options[:optimize] = o
|
100
|
-
end
|
101
|
-
|
102
96
|
parser.on('--contrast CONTRAST',
|
103
97
|
'Apply contrast adjustment, scaled from -2.0 to 2.0 (default 1)') do |c|
|
104
98
|
options[:contrast] = c
|
@@ -239,19 +233,13 @@ module Video2gif
|
|
239
233
|
exit
|
240
234
|
end
|
241
235
|
|
242
|
-
if !is_executable?('convert') && options[:optimize]
|
243
|
-
logger.warn('ImageMagick isn\'t available! Optimization will be'\
|
244
|
-
' disabled!') unless options[:quiet]
|
245
|
-
options[:optimize] = false
|
246
|
-
end
|
247
|
-
|
248
236
|
options
|
249
237
|
end
|
250
238
|
|
251
239
|
def self.build_filter_complex(options)
|
252
|
-
fps
|
253
|
-
|
254
|
-
width
|
240
|
+
fps = options[:fps] || 15
|
241
|
+
max_colors = options[:palette] ? "max_colors=#{options[:palette]}:" : ''
|
242
|
+
width = options[:width] # default is not to scale at all
|
255
243
|
|
256
244
|
# create filter elements
|
257
245
|
fps_filter = "fps=#{fps}"
|
@@ -275,17 +263,17 @@ module Video2gif
|
|
275
263
|
end
|
276
264
|
eq_filter = if options[:eq]
|
277
265
|
'eq=' + %W[
|
278
|
-
contrast=#{options[:contrast] || 1}
|
279
|
-
brightness=#{options[:brightness] || 0}
|
280
|
-
saturation=#{options[:saturation] || 1}
|
281
|
-
gamma=#{options[:gamma] || 1}
|
282
|
-
gamma_r=#{options[:gamma_r] || 1}
|
283
|
-
gamma_g=#{options[:gamma_g] || 1}
|
284
|
-
gamma_b=#{options[:gamma_b] || 1}
|
266
|
+
contrast=#{ options[:contrast] || 1 }
|
267
|
+
brightness=#{ options[:brightness] || 0 }
|
268
|
+
saturation=#{ options[:saturation] || 1 }
|
269
|
+
gamma=#{ options[:gamma] || 1 }
|
270
|
+
gamma_r=#{ options[:gamma_r] || 1 }
|
271
|
+
gamma_g=#{ options[:gamma_g] || 1 }
|
272
|
+
gamma_b=#{ options[:gamma_b] || 1 }
|
285
273
|
].join(':')
|
286
274
|
end
|
287
|
-
palettegen_filter = "palettegen
|
288
|
-
paletteuse_filter = 'paletteuse=dither=
|
275
|
+
palettegen_filter = "palettegen=#{max_colors}stats_mode=diff"
|
276
|
+
paletteuse_filter = 'paletteuse=dither=floyd_steinberg:diff_mode=rectangle'
|
289
277
|
drawtext_filter = if options[:text]
|
290
278
|
count_of_lines = options[:text].scan(/\\n/).count + 1
|
291
279
|
|
@@ -321,10 +309,10 @@ module Video2gif
|
|
321
309
|
# before applying the palettegen so that we accurately predict the
|
322
310
|
# final palette
|
323
311
|
filter_complex << fps_filter
|
324
|
-
filter_complex << crop_filter
|
325
|
-
filter_complex << scale_filter
|
312
|
+
filter_complex << crop_filter if crop_filter
|
313
|
+
filter_complex << scale_filter if options[:width] unless options[:tonemap]
|
326
314
|
filter_complex << tonemap_filters if options[:tonemap]
|
327
|
-
filter_complex << eq_filter
|
315
|
+
filter_complex << eq_filter if options[:eq]
|
328
316
|
filter_complex << drawtext_filter if options[:text]
|
329
317
|
|
330
318
|
# then generate the palette (and label this filter stream)
|
@@ -336,10 +324,10 @@ module Video2gif
|
|
336
324
|
# affected by scaling)
|
337
325
|
filter_complex << '[0:v][palette]' + paletteuse_filter
|
338
326
|
filter_complex << fps_filter
|
339
|
-
filter_complex << crop_filter
|
340
|
-
filter_complex << scale_filter
|
327
|
+
filter_complex << crop_filter if crop_filter
|
328
|
+
filter_complex << scale_filter if options[:width] unless options[:tonemap]
|
341
329
|
filter_complex << tonemap_filters if options[:tonemap]
|
342
|
-
filter_complex << eq_filter
|
330
|
+
filter_complex << eq_filter if options[:eq]
|
343
331
|
filter_complex << drawtext_filter if options[:text]
|
344
332
|
|
345
333
|
filter_complex.join(',')
|
@@ -349,51 +337,38 @@ module Video2gif
|
|
349
337
|
if args[1]
|
350
338
|
args[1].end_with?('.gif') ? args[1] : args[1] + '.gif'
|
351
339
|
else
|
352
|
-
File.join(File.dirname(args[0]),
|
353
|
-
File.basename(args[0], '.*') + '.gif')
|
340
|
+
File.join(File.dirname(args[0]), File.basename(args[0], '.*') + '.gif')
|
354
341
|
end
|
355
342
|
end
|
356
343
|
|
357
|
-
def self.
|
358
|
-
command = []
|
359
|
-
command << 'ffmpeg'
|
360
|
-
command << '-y' # always overwrite
|
344
|
+
def self.build_ffmpeg_cropdetect_command(args, options, logger)
|
345
|
+
command = ['ffmpeg']
|
361
346
|
command << '-analyzeduration' << '2147483647' << '-probesize' << '2147483647'
|
362
347
|
command << '-nostdin'
|
363
348
|
command << '-ss' << options[:seek] if options[:seek]
|
364
349
|
command << '-t' << options[:time] if options[:time]
|
365
350
|
command << '-i' << args[0]
|
366
|
-
command << '-filter_complex' <<
|
367
|
-
command << '-f' << '
|
368
|
-
|
369
|
-
# if we're not optimizing, we won't send to stdout
|
370
|
-
command << (options[:optimize] ? '-' : build_output_filename(args))
|
371
|
-
|
372
|
-
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
|
373
|
-
|
374
|
-
command
|
375
|
-
end
|
376
|
-
|
377
|
-
def self.build_convert_optimize_command(args, options, logger)
|
378
|
-
command = []
|
379
|
-
command << 'convert' << '-' << '-layers' << 'Optimize' << build_output_filename(args)
|
351
|
+
command << '-filter_complex' << "cropdetect=limit=#{options[:cropdetect]}"
|
352
|
+
command << '-f' << 'null'
|
353
|
+
command << '-'
|
380
354
|
|
381
355
|
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
|
382
356
|
|
383
357
|
command
|
384
358
|
end
|
385
359
|
|
386
|
-
def self.
|
387
|
-
command = []
|
388
|
-
command << '
|
360
|
+
def self.build_ffmpeg_gif_command(args, options, logger)
|
361
|
+
command = ['ffmpeg']
|
362
|
+
command << '-y' # always overwrite
|
389
363
|
command << '-analyzeduration' << '2147483647' << '-probesize' << '2147483647'
|
390
364
|
command << '-nostdin'
|
391
365
|
command << '-ss' << options[:seek] if options[:seek]
|
392
366
|
command << '-t' << options[:time] if options[:time]
|
393
367
|
command << '-i' << args[0]
|
394
|
-
command << '-filter_complex' <<
|
395
|
-
command << '-
|
396
|
-
command << '-'
|
368
|
+
command << '-filter_complex' << build_filter_complex(options)
|
369
|
+
command << '-gifflags' << '+transdiff' # enabled by default
|
370
|
+
command << '-f' << 'gif'
|
371
|
+
command << build_output_filename(args)
|
397
372
|
|
398
373
|
logger.info(command.join(' ')) if options[:verbose] unless options[:quiet]
|
399
374
|
|
@@ -405,7 +380,7 @@ module Video2gif
|
|
405
380
|
options = parse_args(ARGV, logger)
|
406
381
|
|
407
382
|
if options[:cropdetect]
|
408
|
-
Open3.popen3(*build_ffmpeg_cropdetect_command(ARGV, options, logger)) do |stdin, stdout, stderr,
|
383
|
+
Open3.popen3(*build_ffmpeg_cropdetect_command(ARGV, options, logger)) do |stdin, stdout, stderr, thread|
|
409
384
|
stdin.close
|
410
385
|
stdout.close
|
411
386
|
stderr.each(chomp: true) do |line|
|
@@ -414,26 +389,19 @@ module Video2gif
|
|
414
389
|
end
|
415
390
|
stderr.close
|
416
391
|
|
417
|
-
raise "Process #{
|
392
|
+
raise "Process #{thread.pid} failed! Try again with --verbose to see error." unless thread.value.success?
|
418
393
|
end
|
419
394
|
end
|
420
395
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
write_io.close
|
427
|
-
if options[:verbose]
|
428
|
-
read_io.each(chomp: true) { |line| logger.info(line) unless options[:quiet] }
|
429
|
-
else
|
430
|
-
read_io.read(1024) until read_io.eof?
|
396
|
+
Open3.popen3(*build_ffmpeg_gif_command(ARGV, options, logger)) do |stdin, stdout, stderr, thread|
|
397
|
+
stdin.close
|
398
|
+
stdout.close
|
399
|
+
stderr.each(chomp: true) do |line|
|
400
|
+
logger.info(line) if options[:verbose] unless options[:quiet]
|
431
401
|
end
|
432
|
-
|
402
|
+
stderr.close
|
433
403
|
|
434
|
-
|
435
|
-
raise "Process #{t.pid} failed! Try again with --verbose to see error." unless t.value.success?
|
436
|
-
end
|
404
|
+
raise "Process #{thread.pid} failed! Try again with --verbose to see error." unless thread.value.success?
|
437
405
|
end
|
438
406
|
end
|
439
407
|
end
|
data/lib/video2gif/version.rb
CHANGED
data/video2gif.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
# the 'allowed_push_host' to allow pushing to a single host or delete
|
18
18
|
# this section to allow pushing to any host.
|
19
19
|
if spec.respond_to?(:metadata)
|
20
|
-
spec.metadata['allowed_push_host'] = 'https://rubygems.org
|
20
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
21
21
|
spec.metadata['homepage_uri'] = spec.homepage
|
22
22
|
spec.metadata['source_code_uri'] = "https://github.com/emilyst/video2gif"
|
23
23
|
# spec.metadata['changelog_uri'] = "https://github.com/emilyst/video2gif"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: video2gif
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emily St.
|
@@ -93,7 +93,7 @@ homepage: https://github.com/emilyst/video2gif
|
|
93
93
|
licenses:
|
94
94
|
- CC0
|
95
95
|
metadata:
|
96
|
-
allowed_push_host: https://rubygems.org
|
96
|
+
allowed_push_host: https://rubygems.org
|
97
97
|
homepage_uri: https://github.com/emilyst/video2gif
|
98
98
|
source_code_uri: https://github.com/emilyst/video2gif
|
99
99
|
post_install_message:
|