video2gif 0.0.13 → 0.0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/video2gif/ffmpeg.rb +70 -40
- data/lib/video2gif/options.rb +11 -0
- data/lib/video2gif/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1266f3c1c715f41fa3c9d15bd11b788c74b4095d
|
4
|
+
data.tar.gz: 33c432d73a9daa08f89b1a758875a504a1c33f8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 820669a53355384b56f7060249a064bc57b1ccd000b575490e055b58ea18cd87438271bf5c0afb99fe139f0feff735a3f4dfd68d72b53dc148018345471b473b
|
7
|
+
data.tar.gz: ae0e081d4cd1ae6fa56a00259c8ffb7132f02ce3eea545cb90f36e788e857034fd3234057beaa03a2c33f30e69ce97ed9b667dace0ae097863eeb1f8625d0885
|
data/Gemfile.lock
CHANGED
data/lib/video2gif/ffmpeg.rb
CHANGED
@@ -3,15 +3,24 @@
|
|
3
3
|
|
4
4
|
module Video2gif
|
5
5
|
module FFMpeg
|
6
|
-
def self.
|
7
|
-
|
6
|
+
def self.filtergraph(options)
|
7
|
+
filtergraph = []
|
8
8
|
|
9
|
-
|
9
|
+
# Set 'fps' filter first, drop unneeded frames instead of
|
10
|
+
# processing those.
|
11
|
+
filtergraph << "fps=#{ options[:fps] || 10 }"
|
10
12
|
|
13
|
+
# Crop if needed, using either settings discovered during the
|
14
|
+
# autocrop run or manually set parameters, so we don't process
|
15
|
+
# additional parts of the image (and exclude it from palette
|
16
|
+
# generation).
|
11
17
|
if options[:autocrop]
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
filtergraph << options[:autocrop]
|
19
|
+
elsif options[:wregion] ||
|
20
|
+
options[:hregion] ||
|
21
|
+
options[:xoffset] ||
|
22
|
+
options[:yoffset]
|
23
|
+
filtergraph << 'crop=' + [
|
15
24
|
"w=#{ options[:wregion] || 'in_w' }",
|
16
25
|
"h=#{ options[:hregion] || 'in_h' }",
|
17
26
|
"x=#{ options[:xoffset] || 0 }",
|
@@ -19,29 +28,39 @@ module Video2gif
|
|
19
28
|
].join(':')
|
20
29
|
end
|
21
30
|
|
31
|
+
# If we're not attempting to convert HDR to SDR, the standard
|
32
|
+
# 'scale' filter is preferred (if we're resizing at all). Scale
|
33
|
+
# here before other filters to avoid unnecessary processing.
|
22
34
|
if options[:width] && !options[:tonemap]
|
23
|
-
|
35
|
+
filtergraph << "scale=flags=lanczos:sws_dither=none:width=#{options[:width]}:height=-1"
|
24
36
|
end
|
25
37
|
|
38
|
+
# If we're attempting to convert HDR to SDR, use a set of 'zscale'
|
39
|
+
# filters, 'format' filters, and the 'tonemap' filter. The
|
40
|
+
# 'zscale' will do the resize for us as well.
|
26
41
|
if options[:tonemap]
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
42
|
+
filtergraph << "zscale=dither=none:filter=lanczos:width=#{options[:width]}:height=-1" if options[:width]
|
43
|
+
filtergraph << 'zscale=transfer=linear:npl=100'
|
44
|
+
filtergraph << 'zscale=npl=100'
|
45
|
+
filtergraph << 'format=gbrpf32le'
|
46
|
+
filtergraph << 'zscale=primaries=bt709'
|
47
|
+
filtergraph << "tonemap=tonemap=#{options[:tonemap]}:desat=0"
|
48
|
+
filtergraph << 'zscale=transfer=bt709:matrix=bt709:range=tv'
|
49
|
+
filtergraph << 'format=yuv420p'
|
35
50
|
end
|
36
51
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
52
|
+
# Perform any desired equalization before we overlay text so that
|
53
|
+
# it won't be affected.
|
54
|
+
filtergraph << "eq=contrast=#{options[:contrast]}" if options[:contrast]
|
55
|
+
filtergraph << "eq=brightness=#{options[:brightness]}" if options[:brightness]
|
56
|
+
filtergraph << "eq=saturation=#{options[:saturation]}" if options[:saturation]
|
57
|
+
filtergraph << "eq=gamma=#{options[:gamma]}" if options[:gamma]
|
58
|
+
filtergraph << "eq=gamma_r=#{options[:gamma_r]}" if options[:gamma_r]
|
59
|
+
filtergraph << "eq=gamma_g=#{options[:gamma_g]}" if options[:gamma_g]
|
60
|
+
filtergraph << "eq=gamma_b=#{options[:gamma_b]}" if options[:gamma_b]
|
61
|
+
|
62
|
+
# If there is text to superimpose, do it here before palette
|
63
|
+
# generation to ensure the color looks appropriate.
|
45
64
|
if options[:text]
|
46
65
|
count_of_lines = options[:text].scan(/\\n/).count + 1
|
47
66
|
text = options[:text]
|
@@ -52,7 +71,7 @@ module Video2gif
|
|
52
71
|
.gsub(/\B"\b([^"\u201C\u201D\u201E\u201F\u2033\u2036\r\n]+)\b?"\B/, "\u201C\\1\u201D")
|
53
72
|
.gsub(/\B'\b([^'\u2018\u2019\u201A\u201B\u2032\u2035\r\n]+)\b?'\B/, "\u2018\\1\u2019")
|
54
73
|
|
55
|
-
|
74
|
+
filtergraph << 'drawtext=' + [
|
56
75
|
"x='#{ options[:xpos] || '(main_w/2-text_w/2)' }'",
|
57
76
|
"y='#{ options[:ypos] || "(main_h-line_h*1.5*#{count_of_lines})" }'",
|
58
77
|
"fontsize='#{ options[:textsize] || 32 }'",
|
@@ -63,21 +82,38 @@ module Video2gif
|
|
63
82
|
].join(':')
|
64
83
|
end
|
65
84
|
|
66
|
-
|
67
|
-
|
68
|
-
|
85
|
+
# Split the stream into two copies, labeled with output pads for
|
86
|
+
# the palettegen/paletteuse filters to use.
|
87
|
+
filtergraph << 'split[palettegen][paletteuse]'
|
88
|
+
|
89
|
+
# Using a copy of the stream created above labeled "palettegen",
|
90
|
+
# generate a palette from the stream using the specified number of
|
91
|
+
# colors and optimizing for moving objects in the stream. Label
|
92
|
+
# this stream's output as "palette."
|
93
|
+
filtergraph << "[palettegen]palettegen=#{options[:palette] || 256}:stats_mode=diff[palette]"
|
94
|
+
|
95
|
+
# Using a copy of the stream from the 'split' filter and the
|
96
|
+
# generated palette as inputs, apply the final palette to the GIF.
|
97
|
+
# For non-moving parts of the GIF, attempt to reuse the same
|
98
|
+
# palette from frame to frame.
|
99
|
+
filtergraph << "[paletteuse][palette]paletteuse=dither=#{options[:dither] || 'floyd_steinberg'}:diff_mode=rectangle"
|
69
100
|
|
70
|
-
|
101
|
+
filtergraph.join(',')
|
71
102
|
end
|
72
103
|
|
73
|
-
def self.
|
74
|
-
command = [
|
104
|
+
def self.ffmpeg_command(options, executable: 'ffmpeg')
|
105
|
+
command = [executable]
|
106
|
+
command << '-y' # always overwrite
|
75
107
|
command << '-analyzeduration' << '2147483647' << '-probesize' << '2147483647'
|
76
108
|
command << '-loglevel' << 'verbose'
|
77
109
|
command << '-ss' << options[:seek] if options[:seek]
|
78
110
|
command << '-t' << options[:time] if options[:time]
|
79
111
|
command << '-i' << options[:input_filename]
|
80
|
-
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.cropdetect_command(options, logger, executable: 'ffmpeg')
|
115
|
+
command = ffmpeg_command(options, executable: executable)
|
116
|
+
command << '-filtergraph' << "cropdetect=limit=#{options[:autocrop]}"
|
81
117
|
command << '-f' << 'null'
|
82
118
|
command << '-'
|
83
119
|
|
@@ -86,15 +122,9 @@ module Video2gif
|
|
86
122
|
command
|
87
123
|
end
|
88
124
|
|
89
|
-
def self.gif_command(options, logger)
|
90
|
-
command =
|
91
|
-
command << '-
|
92
|
-
command << '-analyzeduration' << '2147483647' << '-probesize' << '2147483647'
|
93
|
-
command << '-loglevel' << 'verbose'
|
94
|
-
command << '-ss' << options[:seek] if options[:seek]
|
95
|
-
command << '-t' << options[:time] if options[:time]
|
96
|
-
command << '-i' << options[:input_filename]
|
97
|
-
command << '-filter_complex' << filter_complex(options)
|
125
|
+
def self.gif_command(options, logger, executable: 'ffmpeg')
|
126
|
+
command = ffmpeg_command(options, executable: executable)
|
127
|
+
command << '-filter_complex' << filtergraph(options)
|
98
128
|
command << '-f' << 'gif'
|
99
129
|
command << options[:output_filename]
|
100
130
|
|
data/lib/video2gif/options.rb
CHANGED
@@ -57,6 +57,17 @@ module Video2gif
|
|
57
57
|
options[:palette] = p
|
58
58
|
end
|
59
59
|
|
60
|
+
parser.on('-d [ALGORITHM]',
|
61
|
+
'--[no-]dither [ALGORITHM]',
|
62
|
+
'Set the dithering algorithm for the palette generation",
|
63
|
+
"(default enabled with "floyd_steinberg")') do |d|
|
64
|
+
if d.nil?
|
65
|
+
options[:dither] = 'floyd_steinberg'
|
66
|
+
else
|
67
|
+
options[:dither] = d || 'none'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
60
71
|
parser.on('-c SIZE',
|
61
72
|
'--crop-size-w SIZE',
|
62
73
|
'Pixel size of width to select from source video, before scaling') do |s|
|
data/lib/video2gif/version.rb
CHANGED