ffmprb 0.12.1 → 0.12.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/Gemfile.lock +1 -1
- data/coverage/index.html +1275 -1176
- data/exp/present/Gemfile.lock +2 -2
- data/exp/present/exp/present.rb +7 -1
- data/exp/youtubby/Gemfile +1 -3
- data/exp/youtubby/Gemfile.lock +3 -5
- data/exp/youtubby/exp/gop-raw-cut-rcc-join-you-HD60.rb +356 -0
- data/exp/youtubby/exp/gop-raw-cut-you-HD60 +3 -1
- data/exp/youtubby/exp/gop-raw-cut-you-HD60.rb +190 -63
- data/lib/defaults.rb +1 -1
- data/lib/ffmprb/file.rb +13 -5
- data/lib/ffmprb/filter.rb +7 -3
- data/lib/ffmprb/process/input/paced.rb +3 -1
- data/lib/ffmprb/process/output.rb +2 -11
- data/lib/ffmprb/process.rb +1 -0
- data/lib/ffmprb/util/thread.rb +6 -3
- data/lib/ffmprb/version.rb +1 -1
- data/tmp/rspec_guard_result +2 -0
- metadata +4 -2
@@ -1,3 +1,93 @@
|
|
1
|
+
|
2
|
+
# The general idea of (a video production pipeline for) "vlogging":
|
3
|
+
# -1. think of something nice to shoot
|
4
|
+
# - maybe even write down a scenario and produce "the picture"
|
5
|
+
# 0. shoot the damn footage with your cam/mic/what-have-you
|
6
|
+
# - press Record on your GoPro (video stored on device)
|
7
|
+
# 1. upload the raw media files to a (cloud) storage
|
8
|
+
# - GoPro media storage subscription (video files accessible at)
|
9
|
+
# 2. take note of, sort and clean the raw footage up manually
|
10
|
+
# - cut and concatenate the media files into cohesive "scenes" (ffmprb script)
|
11
|
+
# 3. upload the HD renders of the raw scenes
|
12
|
+
# - to a "cache" storage (ghlr media), plus, for the public access (YouTube)
|
13
|
+
# 4. compose a video from the raw scene cuts and additional media
|
14
|
+
# - create a (ffmprb) montage script using the media
|
15
|
+
# 5. upload and premiere the video piece versions (final cut, general public)
|
16
|
+
# - to "ghlr media sharing" (fut.), plus, for public "discovery" (YouTube)
|
17
|
+
# 6. profit?
|
18
|
+
|
19
|
+
# # empty (micro) case is raw publish
|
20
|
+
|
21
|
+
# NOTE on simprender:
|
22
|
+
# a title-back-summary effect
|
23
|
+
# XXX
|
24
|
+
# -16(2) -8(2) -4(2) ^0 2(2), -4(1) [1]
|
25
|
+
# crop
|
26
|
+
# ?soundtrack?
|
27
|
+
# cut(from 24, to: 56).pace(16).reverse
|
28
|
+
# cut(from 8, to: 24).pace(8).reverse
|
29
|
+
# cut(from 0, to: 8).pace(4).reverse
|
30
|
+
# cut(from: 0, to: 4).pace(2)
|
31
|
+
# cut(from: 0, to: 4).pace(4).reverse
|
32
|
+
#
|
33
|
+
# 2.0
|
34
|
+
# crop(0.48).cut(from: M).pace(m).reverse
|
35
|
+
# ...
|
36
|
+
# crop(0.2).cut(from: 12, to: 28).pace(16).reverse
|
37
|
+
# crop(0.18).cut(from: 4, to: 12).pace(8).reverse
|
38
|
+
# crop(0.15).cut(from: 0, to: 4).pace(4).reverse
|
39
|
+
# crop(0.1).cut(from: 0, to: 4).pace(2)
|
40
|
+
# crop(0.05).cut(from: 0, to: 4).pace(4).reverse
|
41
|
+
#
|
42
|
+
# 3.0 (aka 1.11)
|
43
|
+
# crop(0.49).cut(from: M).pace(m).reverse
|
44
|
+
# ...
|
45
|
+
# crop(0.2).cut(from: 12, to: 28).pace(16).reverse
|
46
|
+
# crop(0.25).cut(from: 4, to: 12).pace(8).reverse
|
47
|
+
# crop(0.14).cut(from: 0, to: 4).pace(4).reverse
|
48
|
+
|
49
|
+
# NOTE looking good?
|
50
|
+
REV_CUT_CROP_EXP_BASE = 1.333
|
51
|
+
|
52
|
+
# NOTE unreasonable to exhaust
|
53
|
+
REV_CUT_CROP_EXP_PRE_CUTS =
|
54
|
+
(2..64).reduce [] do |a, k|
|
55
|
+
if (3.6..3600.0).include? (int = REV_CUT_CROP_EXP_BASE**k)
|
56
|
+
a << (a[-1] || 0) + int
|
57
|
+
else
|
58
|
+
a
|
59
|
+
end
|
60
|
+
end.reverse
|
61
|
+
|
62
|
+
# NOTE reasonable to look good
|
63
|
+
REV_CUT_CROP_LENGTH_MIN_S = REV_CUT_CROP_EXP_PRE_CUTS[-4]
|
64
|
+
|
65
|
+
# XXX Can also go hard on with blending to complement the rewind effect...
|
66
|
+
|
67
|
+
def rev_cut_crop_seq(length, inp)
|
68
|
+
fail "supply a block that receives the next reel and returns the next input" unless
|
69
|
+
block_given?
|
70
|
+
|
71
|
+
return unless
|
72
|
+
length > REV_CUT_CROP_LENGTH_MIN_S
|
73
|
+
|
74
|
+
REV_CUT_CROP_EXP_PRE_CUTS.each_with_index do |k, i|
|
75
|
+
next if
|
76
|
+
(n = REV_CUT_CROP_EXP_PRE_CUTS[i + 1] || 0) > length
|
77
|
+
cut = {from: n}
|
78
|
+
cut[:to] = k unless
|
79
|
+
k > length
|
80
|
+
pace = REV_CUT_CROP_EXP_BASE**(REV_CUT_CROP_EXP_PRE_CUTS.length - i + 1)
|
81
|
+
# XXX Math.log(1 + (REV_CUT_CROP_EXP_PRE_CUTS.length - i + 2) / 5.0) / 4 # NOTE magick!
|
82
|
+
crop = 0.5*(1 - Math.sqrt(1/pace)) # NOTE bitrate! (x2)
|
83
|
+
# inp = yield(inp.crop(crop).cut(cut).pace(pace).reverse)
|
84
|
+
yield inp.crop(crop).cut(cut).pace(pace).reverse
|
85
|
+
end
|
86
|
+
# XXX
|
87
|
+
# inp = yield(inp.crop(0.1).cut(from: 0, to: 4).pace(2))
|
88
|
+
# inp = yield(inp.crop(0.05).cut(from: 0, to: 4).pace(4).reverse)
|
89
|
+
end
|
90
|
+
|
1
91
|
channel = ARGV.shift || 'default'
|
2
92
|
|
3
93
|
abort "USAGE: gop-raw-cut-you-HD60.rb [CHANNEL]" unless
|
@@ -6,8 +96,8 @@ abort "USAGE: gop-raw-cut-you-HD60.rb [CHANNEL]" unless
|
|
6
96
|
MEDIA_DIR = ENV['MEDIA_DIR'] or
|
7
97
|
abort "MEDIA_DIR needed"
|
8
98
|
|
9
|
-
|
10
|
-
title = "Topublish uploaded at #{
|
99
|
+
now_time = Time.now
|
100
|
+
title = "XXX Topublish (uploaded at #{now_time.strftime '%y-%m-%d-%H-%M'})"
|
11
101
|
|
12
102
|
require 'cgi'
|
13
103
|
|
@@ -26,14 +116,16 @@ end
|
|
26
116
|
require 'fileutils'
|
27
117
|
|
28
118
|
require 'ffmprb'
|
29
|
-
|
119
|
+
Ffmprb.debug = true # XXX
|
30
120
|
Ffmprb::Util::Thread.timeout = 150
|
31
121
|
|
32
122
|
int_video_opt = {resolution: Ffmprb::HD_4K, fps: 60}
|
33
|
-
|
34
|
-
|
123
|
+
raw_video_opt = {resolution: Ffmprb::HD_4K, fps: 60, encoder: 'libx264 -crf 15'} # XXX -preset superfast
|
124
|
+
fin_video_opt = {resolution: Ffmprb::HD_1080p, fps: 60, encoder: 'libx265 -crf 19'} # XXX 21 -preset veryslow
|
125
|
+
YOU_VIDEO_OPT = {resolution: Ffmprb::HD_4K, fps: 60, encoder: 'libx264 -crf 17'} # XXX 15 -preset superfast
|
35
126
|
|
36
|
-
|
127
|
+
GOP_FILE_PREFIX = 'GX'
|
128
|
+
GOP_MP4_RE = /\b(#{GOP_FILE_PREFIX}(\d\d)(\d\d\d\d)\.MP4)\b/i
|
37
129
|
GOP_ZIP_URL_RE = %r[/zip/]i
|
38
130
|
|
39
131
|
|
@@ -43,10 +135,11 @@ def dura_to_sec(dura_str)
|
|
43
135
|
end
|
44
136
|
end
|
45
137
|
|
46
|
-
def
|
47
|
-
File.join MEDIA_DIR, "#{name}.mp4"
|
138
|
+
def date_media_path(date, name)
|
139
|
+
File.join MEDIA_DIR, '%04d' % date.year, '%02d' % date.month, '%02d' % date.day, "#{name}.mp4"
|
48
140
|
end
|
49
141
|
|
142
|
+
raw_time = nil
|
50
143
|
|
51
144
|
FileUtils.mkdir_p (tmp_dir = File.join(MEDIA_DIR, 'gop-raw-cut-you-tmp'))
|
52
145
|
begin
|
@@ -56,12 +149,13 @@ begin
|
|
56
149
|
warn "\nEnter lines containing GoP media D/L URLs and cut times:\n\n"
|
57
150
|
|
58
151
|
av_src_cuts = []
|
152
|
+
int_av_path = nil
|
59
153
|
dl_q = Queue.new
|
60
154
|
|
61
|
-
shots = []
|
62
155
|
fetcher = Thread.new do
|
63
156
|
while (url, cuts = dl_q.deq)
|
64
157
|
srcs = []
|
158
|
+
shot = nil
|
65
159
|
while srcs.empty? # NOTE sometimes (zip) D/L silently fails, see below
|
66
160
|
name =
|
67
161
|
case CGI.unescape url
|
@@ -80,16 +174,28 @@ begin
|
|
80
174
|
zip_lines.each do |line|
|
81
175
|
if line =~ GOP_MP4_RE
|
82
176
|
srcs << $1
|
83
|
-
|
177
|
+
shot = $3
|
84
178
|
end
|
85
179
|
end
|
86
180
|
end
|
87
181
|
File.delete name
|
88
182
|
else
|
89
183
|
srcs << name
|
90
|
-
|
184
|
+
shot = $3
|
91
185
|
end
|
92
186
|
end
|
187
|
+
|
188
|
+
# NOTE assuming srcs is not empty, for the first src
|
189
|
+
unless raw_time
|
190
|
+
raw_time =
|
191
|
+
Ffmprb::File.access(srcs[0]).creation_time ||
|
192
|
+
now_time # NOTE well...
|
193
|
+
int_av_path = date_media_path(raw_time, "#{GOP_FILE_PREFIX}-#{shot}")
|
194
|
+
# XXX
|
195
|
+
# break if
|
196
|
+
# (Ffmprb::File.access(int_av_path).length rescue 0) > 0
|
197
|
+
end
|
198
|
+
|
93
199
|
av_src_cuts << [
|
94
200
|
srcs.sort do |a, b|
|
95
201
|
a_m = GOP_MP4_RE.match(a)
|
@@ -103,6 +209,9 @@ begin
|
|
103
209
|
cuts
|
104
210
|
]
|
105
211
|
end
|
212
|
+
|
213
|
+
abort "ERROR no inputs given" unless
|
214
|
+
int_av_path
|
106
215
|
end
|
107
216
|
|
108
217
|
while (url_cut = gets)
|
@@ -123,20 +232,17 @@ begin
|
|
123
232
|
warn "\nFetching those files..."
|
124
233
|
fetcher.join
|
125
234
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
out_name = "GX-#{shots.uniq.join '-'}-#{time_s}"
|
130
|
-
you_out_path = "_you_#{out_name}.mp4"
|
131
|
-
warn "\nCut-catting to out (#{out_name}) paths + you..."
|
235
|
+
out_path = date_media_path(now_time, "#{GOP_FILE_PREFIX}-#{raw_time.strftime '%y-%m-%d-%H-%M'}-simprender")
|
236
|
+
you_out_path = "_you_toul.mp4"
|
237
|
+
warn "\nCut-catting to cache (#{int_av_path})"
|
132
238
|
|
133
239
|
pipe_cut_threads = av_src_cuts.map do |srcs, cuts|
|
134
240
|
[
|
135
|
-
(
|
241
|
+
(tmp_av_stream = Ffmprb::File.temp_fifo('.flv')),
|
136
242
|
cuts.each_slice(2).map { |from, to| {from: from, to: to} },
|
137
243
|
Thread.new do
|
138
244
|
Ffmprb.process do
|
139
|
-
output
|
245
|
+
output tmp_av_stream, video: int_video_opt do
|
140
246
|
srcs.each do |src|
|
141
247
|
roll input src
|
142
248
|
end
|
@@ -146,47 +252,80 @@ begin
|
|
146
252
|
]
|
147
253
|
end
|
148
254
|
|
149
|
-
Ffmprb::File.temp_fifo('.flv') do |
|
255
|
+
Ffmprb::File.temp_fifo('.flv') do |av_stream|
|
150
256
|
thr = Thread.new do
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
257
|
+
unless pipe_cut_threads.empty?
|
258
|
+
FileUtils.mkdir_p File.dirname int_av_path
|
259
|
+
Ffmprb.process do
|
260
|
+
inp_cut_opts =
|
261
|
+
pipe_cut_threads.map do |tmp_av_stream, cut_opts, _|
|
262
|
+
(cut_opts.empty?? [{}] : cut_opts).map do |cut_opt|
|
263
|
+
[input(tmp_av_stream), cut_opt]
|
264
|
+
end
|
265
|
+
end.reduce :+
|
266
|
+
# XXX output int_av_path, video: raw_video_opt do
|
267
|
+
output av_stream, video: raw_video_opt do
|
268
|
+
inp_cut_opts.each do |inp, cut_opt|
|
269
|
+
roll inp.cut cut_opt
|
270
|
+
end
|
161
271
|
end
|
162
272
|
end
|
163
|
-
# [Rational(1)/8, Rational(1)/4, Rational(1)/2, 1, 2, 4, 8].each do |r| # XXX
|
164
|
-
# output out_path("#{out_name}x#{r.to_f}"), video: fin_video_opt do
|
165
|
-
# inp_cut_opts.each do |inp, cut_opt|
|
166
|
-
# roll inp.cut(cut_opt).pace r
|
167
|
-
# end
|
168
|
-
# end
|
169
|
-
# end
|
170
273
|
|
171
|
-
# XXX
|
172
|
-
#
|
173
|
-
#
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
274
|
+
# XXX this is flawed:
|
275
|
+
# the simple threads fail because of oom docker signals (9)
|
276
|
+
# (not because of broken pipes)
|
277
|
+
pipe_cut_threads.each do |tmp_av_stream, _, thr|
|
278
|
+
begin
|
279
|
+
thr.join
|
280
|
+
rescue
|
281
|
+
warn "WARN errors-a-happening: #{$!}"
|
282
|
+
end
|
283
|
+
tmp_av_stream.unlink
|
284
|
+
end
|
182
285
|
end
|
286
|
+
|
287
|
+
# XXX
|
288
|
+
# warn "\nComposing and rendering to out (#{out_path}) + you..."
|
289
|
+
# Ffmprb.process do
|
290
|
+
# output av_stream, video: int_video_opt do
|
291
|
+
# # XXX roll in1.crop(0.25).cut(from: Ffmprb::File.access(int_av_path).length - 512).pace(16).reverse
|
292
|
+
|
293
|
+
# rev_cut_crop_seq(Ffmprb::File.access(int_av_path).length, input(int_av_path)) do |reel|
|
294
|
+
# roll reel
|
295
|
+
# end
|
296
|
+
# roll input(int_av_path)
|
297
|
+
# end
|
298
|
+
# end
|
299
|
+
# [Rational(1)/8, Rational(1)/4, Rational(1)/2, 1, 2, 4, 8].each do |r| # XXX
|
300
|
+
# output out_path("#{out_name}x#{r.to_f}"), video: fin_video_opt do
|
301
|
+
# inp_cut_opts.each do |inp, cut_opt|
|
302
|
+
# roll inp.cut(cut_opt).pace r
|
303
|
+
# end
|
304
|
+
# end
|
305
|
+
# end
|
306
|
+
|
307
|
+
# XXX
|
308
|
+
# output out_path("#{out_name}x-8"), video: fin_video_opt do
|
309
|
+
# inp_cut_opts.each do |inp, cut_opt|
|
310
|
+
# roll inp.cut(cut_opt).reverse.pace 8
|
311
|
+
# end
|
312
|
+
# end
|
313
|
+
# output out_path("#{out_name}x8-"), video: fin_video_opt do
|
314
|
+
# inp_cut_opts.each do |inp, cut_opt|
|
315
|
+
# roll inp.cut(cut_opt).pace(8).reverse
|
316
|
+
# end
|
317
|
+
# end
|
183
318
|
end
|
319
|
+
# XXX bad romance: abort from any thread
|
184
320
|
begin
|
321
|
+
FileUtils.mkdir_p File.dirname out_path
|
185
322
|
Ffmprb.process do
|
186
|
-
in1 = input(
|
323
|
+
in1 = input(av_stream)
|
187
324
|
output you_out_path, video: YOU_VIDEO_OPT do
|
188
|
-
roll in1
|
189
|
-
|
325
|
+
roll in1
|
326
|
+
end
|
327
|
+
output out_path, video: fin_video_opt do
|
328
|
+
roll in1 # XXX .pp
|
190
329
|
end
|
191
330
|
end
|
192
331
|
ensure
|
@@ -195,18 +334,6 @@ begin
|
|
195
334
|
end
|
196
335
|
|
197
336
|
|
198
|
-
# XXX this is flawed:
|
199
|
-
# the simple threads fail because of oom docker signals (9)
|
200
|
-
# (not because of broken pipes)
|
201
|
-
pipe_cut_threads.each do |av_pipe, _, thr|
|
202
|
-
begin
|
203
|
-
thr.join
|
204
|
-
rescue
|
205
|
-
warn "WARN errors-a-happening: #{$!}"
|
206
|
-
end
|
207
|
-
av_pipe.unlink
|
208
|
-
end
|
209
|
-
|
210
337
|
metadata = {
|
211
338
|
snippet: {
|
212
339
|
title: title
|
data/lib/defaults.rb
CHANGED
data/lib/ffmprb/file.rb
CHANGED
@@ -95,7 +95,8 @@ module Ffmprb
|
|
95
95
|
|
96
96
|
def initialize(path:, mode:)
|
97
97
|
@mode = mode.to_sym
|
98
|
-
fail Error, "Open for read, create for write, ??? for #{@mode}" unless
|
98
|
+
fail Error, "Open for read, create for write, ??? for #{@mode}" unless
|
99
|
+
%i[read write].include?(@mode)
|
99
100
|
@path = path
|
100
101
|
@path.close if @path && @path.respond_to?(:close) # NOTE we operate on closed files
|
101
102
|
path! # NOTE early (exception) raiser
|
@@ -147,11 +148,20 @@ module Ffmprb
|
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
150
|
-
def resolution
|
151
|
-
v_stream = probe['streams'].first
|
151
|
+
def resolution(force=false)
|
152
|
+
v_stream = probe(force)['streams'].first
|
152
153
|
"#{v_stream['width']}x#{v_stream['height']}"
|
153
154
|
end
|
154
155
|
|
156
|
+
def fps(force=false)
|
157
|
+
v_stream = probe(force)['streams'].first
|
158
|
+
Rational v_stream['r_frame_rate'] || v_stream['avg_frame_rate']
|
159
|
+
end
|
160
|
+
|
161
|
+
def creation_time(force=false)
|
162
|
+
Time.parse probe(force)['format']['tags']['creation_time']
|
163
|
+
end
|
164
|
+
|
155
165
|
|
156
166
|
# Manipulation
|
157
167
|
|
@@ -191,9 +201,7 @@ module Ffmprb
|
|
191
201
|
fail Error, "This doesn't look like a ffprobable file" unless probe['streams']
|
192
202
|
end
|
193
203
|
end
|
194
|
-
|
195
204
|
end
|
196
|
-
|
197
205
|
end
|
198
206
|
|
199
207
|
require_relative 'file/sample'
|
data/lib/ffmprb/filter.rb
CHANGED
@@ -49,6 +49,7 @@ module Ffmprb
|
|
49
49
|
inout 'asplit', inputs, outputs
|
50
50
|
end
|
51
51
|
|
52
|
+
# TODO? fix "Queue input is backward in time"
|
52
53
|
def areverse(input=nil, output=nil)
|
53
54
|
inout 'areverse', input, output
|
54
55
|
end
|
@@ -184,7 +185,7 @@ module Ffmprb
|
|
184
185
|
inout 'fps=fps=%{fps}', input, output, fps: fps
|
185
186
|
end
|
186
187
|
|
187
|
-
def
|
188
|
+
def framerate(fps, input=nil, output=nil)
|
188
189
|
inout 'framerate=fps=%{fps}', input, output, fps: fps
|
189
190
|
end
|
190
191
|
# TODO other effects like... minterpolate=fps=%{fps}:mi_mode=mci:mc_mode=aobmc:vsbmc=1
|
@@ -220,8 +221,11 @@ module Ffmprb
|
|
220
221
|
inout 'setsar=%{ratio}', input, output, ratio: ratio
|
221
222
|
end
|
222
223
|
|
223
|
-
def
|
224
|
-
inout
|
224
|
+
def setpts_framerate(ratio, fps, input=nil, output=nil)
|
225
|
+
inout [
|
226
|
+
inout('setpts=%{r_fps}*PTS', r_fps: 1.0/ratio),
|
227
|
+
*framerate(fps),
|
228
|
+
].join(', '), input, output
|
225
229
|
end
|
226
230
|
|
227
231
|
def scale(resolution, input=nil, output=nil)
|
@@ -19,13 +19,15 @@ module Ffmprb
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def filters_for(lbl, video:, audio:)
|
22
|
+
fail Error, "pacing requires fps" unless
|
23
|
+
video.fps
|
22
24
|
|
23
25
|
# Pacing
|
24
26
|
|
25
27
|
lbl_aux = "pc#{lbl}"
|
26
28
|
super(lbl_aux, video: video, audio: audio) +
|
27
29
|
[
|
28
|
-
*((video && channel?(:video))? Filter.
|
30
|
+
*((video && channel?(:video))? Filter.setpts_framerate(@ratio, video.fps, "#{lbl_aux}:v", "#{lbl}:v"): nil),
|
29
31
|
*((audio && channel?(:audio))? Filter.atempo(@ratio, "#{lbl_aux}:a", "#{lbl}:a"): nil)
|
30
32
|
]
|
31
33
|
end
|
@@ -89,19 +89,13 @@ module Ffmprb
|
|
89
89
|
# NOTE mapping input to this lbl
|
90
90
|
|
91
91
|
lbl = "o#{idx}rl#{i}"
|
92
|
-
lbl_aux = "t#{lbl}"
|
93
92
|
|
94
93
|
# NOTE Image-Padding to match the target resolution
|
95
94
|
# TODO full screen only at the moment (see exception above)
|
96
95
|
|
97
96
|
Ffmprb.logger.debug{"#{self} asking for filters of #{curr_reel.reel.io.inspect} video: #{channel(:video)}, audio: #{channel(:audio)}"}
|
98
|
-
|
99
|
-
|
100
|
-
*curr_reel.reel.filters_for(lbl_aux, video: channel(:video), audio: channel(:audio)),
|
101
|
-
*(channel?(:video)? Filter.interpolate_v(video_fps, "#{lbl_aux}:v", "#{lbl}:v"): nil),
|
102
|
-
*(channel?(:audio)? Filter.anull("#{lbl_aux}:a", "#{lbl}:a"): nil)
|
103
|
-
]
|
104
|
-
)
|
97
|
+
# NOTE may require changes if fps is different (and ffmpeg freezes)
|
98
|
+
@filters.concat curr_reel.reel.filters_for(lbl, video: channel(:video), audio: channel(:audio))
|
105
99
|
end
|
106
100
|
|
107
101
|
trim_prev_at = curr_reel.after || (curr_reel.transition && 0)
|
@@ -398,9 +392,6 @@ module Ffmprb
|
|
398
392
|
(@overlays ||= []) <<
|
399
393
|
OpenStruct.new(reel: reel, at: at, duck: duck)
|
400
394
|
end
|
401
|
-
|
402
395
|
end
|
403
|
-
|
404
396
|
end
|
405
|
-
|
406
397
|
end
|
data/lib/ffmprb/process.rb
CHANGED
data/lib/ffmprb/util/thread.rb
CHANGED
@@ -59,7 +59,8 @@ module Ffmprb
|
|
59
59
|
@parent.child_lives self
|
60
60
|
Ffmprb.logger.warn "Not the main: false thread run by a #{self.class.name} thread" if main
|
61
61
|
else
|
62
|
-
Ffmprb.logger.warn "Not the main: true thread run by a not #{self.class.name} thread" unless
|
62
|
+
Ffmprb.logger.warn "Not the main: true thread run by a not #{self.class.name} thread" unless
|
63
|
+
main
|
63
64
|
end
|
64
65
|
sync_q.enq :ok
|
65
66
|
Ffmprb.logger.debug{"#{name} thread launched"}
|
@@ -99,7 +100,8 @@ module Ffmprb
|
|
99
100
|
@children_mon.synchronize do
|
100
101
|
Ffmprb.logger.debug{"releasing #{thr.name} thread"}
|
101
102
|
@dead_children_q.enq thr
|
102
|
-
fail "System Error" unless
|
103
|
+
fail "System Error" unless
|
104
|
+
@live_children.delete thr
|
103
105
|
end
|
104
106
|
proc_vis_edge self, thr, :remove
|
105
107
|
end
|
@@ -112,7 +114,8 @@ module Ffmprb
|
|
112
114
|
@dead_children_q.deq
|
113
115
|
end
|
114
116
|
Ffmprb.logger.debug "joining the late #{thr.name} thread"
|
115
|
-
fail "System Error" unless
|
117
|
+
fail "System Error" unless
|
118
|
+
thr.join(timeout) # NOTE should not block
|
116
119
|
end
|
117
120
|
end
|
118
121
|
end
|
data/lib/ffmprb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffmprb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Costa Shapiro
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: mkfifo
|
@@ -189,6 +189,7 @@ files:
|
|
189
189
|
- exp/youtubby/README.md
|
190
190
|
- exp/youtubby/bin/up-deps
|
191
191
|
- exp/youtubby/docker-compose.yml
|
192
|
+
- exp/youtubby/exp/gop-raw-cut-rcc-join-you-HD60.rb
|
192
193
|
- exp/youtubby/exp/gop-raw-cut-you-HD60
|
193
194
|
- exp/youtubby/exp/gop-raw-cut-you-HD60.rb
|
194
195
|
- exp/youtubby/exp/media-upload
|
@@ -234,6 +235,7 @@ files:
|
|
234
235
|
- tmp/exp/src/SAM_3132.MP4
|
235
236
|
- tmp/ffmprb-0.11.4.gem
|
236
237
|
- tmp/output.rb
|
238
|
+
- tmp/rspec_guard_result
|
237
239
|
homepage: https://github.com/costa/ffmprb
|
238
240
|
licenses: []
|
239
241
|
metadata: {}
|