ffmprb 0.11.3 → 0.11.4

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.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/Dockerfile +12 -0
  3. data/Gemfile +8 -1
  4. data/Gemfile.lock +121 -0
  5. data/README.md +10 -8
  6. data/TODO.md +1 -0
  7. data/bin/test +7 -0
  8. data/coverage/assets/0.10.0/application.css +799 -0
  9. data/coverage/assets/0.10.0/application.js +1707 -0
  10. data/coverage/assets/0.10.0/colorbox/border.png +0 -0
  11. data/coverage/assets/0.10.0/colorbox/controls.png +0 -0
  12. data/coverage/assets/0.10.0/colorbox/loading.gif +0 -0
  13. data/coverage/assets/0.10.0/colorbox/loading_background.png +0 -0
  14. data/coverage/assets/0.10.0/favicon_green.png +0 -0
  15. data/coverage/assets/0.10.0/favicon_red.png +0 -0
  16. data/coverage/assets/0.10.0/favicon_yellow.png +0 -0
  17. data/coverage/assets/0.10.0/loading.gif +0 -0
  18. data/coverage/assets/0.10.0/magnify.png +0 -0
  19. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  20. data/coverage/assets/0.10.0/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  21. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  22. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  23. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  24. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  25. data/coverage/assets/0.10.0/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  26. data/coverage/assets/0.10.0/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  27. data/coverage/assets/0.10.0/smoothness/images/ui-icons_222222_256x240.png +0 -0
  28. data/coverage/assets/0.10.0/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  29. data/coverage/assets/0.10.0/smoothness/images/ui-icons_454545_256x240.png +0 -0
  30. data/coverage/assets/0.10.0/smoothness/images/ui-icons_888888_256x240.png +0 -0
  31. data/coverage/assets/0.10.0/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  32. data/coverage/assets/0.10.2/application.css +799 -0
  33. data/coverage/assets/0.10.2/application.js +1707 -0
  34. data/coverage/assets/0.10.2/colorbox/border.png +0 -0
  35. data/coverage/assets/0.10.2/colorbox/controls.png +0 -0
  36. data/coverage/assets/0.10.2/colorbox/loading.gif +0 -0
  37. data/coverage/assets/0.10.2/colorbox/loading_background.png +0 -0
  38. data/coverage/assets/0.10.2/favicon_green.png +0 -0
  39. data/coverage/assets/0.10.2/favicon_red.png +0 -0
  40. data/coverage/assets/0.10.2/favicon_yellow.png +0 -0
  41. data/coverage/assets/0.10.2/loading.gif +0 -0
  42. data/coverage/assets/0.10.2/magnify.png +0 -0
  43. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  44. data/coverage/assets/0.10.2/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  45. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  46. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  47. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  48. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  49. data/coverage/assets/0.10.2/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  50. data/coverage/assets/0.10.2/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  51. data/coverage/assets/0.10.2/smoothness/images/ui-icons_222222_256x240.png +0 -0
  52. data/coverage/assets/0.10.2/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  53. data/coverage/assets/0.10.2/smoothness/images/ui-icons_454545_256x240.png +0 -0
  54. data/coverage/assets/0.10.2/smoothness/images/ui-icons_888888_256x240.png +0 -0
  55. data/coverage/assets/0.10.2/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  56. data/coverage/assets/0.12.2/DataTables-1.10.20/images/sort_asc.png +0 -0
  57. data/coverage/assets/0.12.2/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
  58. data/coverage/assets/0.12.2/DataTables-1.10.20/images/sort_both.png +0 -0
  59. data/coverage/assets/0.12.2/DataTables-1.10.20/images/sort_desc.png +0 -0
  60. data/coverage/assets/0.12.2/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
  61. data/coverage/assets/0.12.2/application.css +1 -0
  62. data/coverage/assets/0.12.2/application.js +7 -0
  63. data/coverage/assets/0.12.2/colorbox/border.png +0 -0
  64. data/coverage/assets/0.12.2/colorbox/controls.png +0 -0
  65. data/coverage/assets/0.12.2/colorbox/loading.gif +0 -0
  66. data/coverage/assets/0.12.2/colorbox/loading_background.png +0 -0
  67. data/coverage/assets/0.12.2/favicon_green.png +0 -0
  68. data/coverage/assets/0.12.2/favicon_red.png +0 -0
  69. data/coverage/assets/0.12.2/favicon_yellow.png +0 -0
  70. data/coverage/assets/0.12.2/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  71. data/coverage/assets/0.12.2/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  72. data/coverage/assets/0.12.2/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  73. data/coverage/assets/0.12.2/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  74. data/coverage/assets/0.12.2/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  75. data/coverage/assets/0.12.2/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  76. data/coverage/assets/0.12.2/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  77. data/coverage/assets/0.12.2/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  78. data/coverage/assets/0.12.2/images/ui-icons_222222_256x240.png +0 -0
  79. data/coverage/assets/0.12.2/images/ui-icons_2e83ff_256x240.png +0 -0
  80. data/coverage/assets/0.12.2/images/ui-icons_454545_256x240.png +0 -0
  81. data/coverage/assets/0.12.2/images/ui-icons_888888_256x240.png +0 -0
  82. data/coverage/assets/0.12.2/images/ui-icons_cd0a0a_256x240.png +0 -0
  83. data/coverage/assets/0.12.2/loading.gif +0 -0
  84. data/coverage/assets/0.12.2/magnify.png +0 -0
  85. data/coverage/index.html +24412 -0
  86. data/ffmprb.gemspec +34 -14
  87. data/lib/defaults.rb +1 -1
  88. data/lib/ffmprb.rb +3 -3
  89. data/lib/ffmprb/file.rb +8 -8
  90. data/lib/ffmprb/file/sample.rb +2 -2
  91. data/lib/ffmprb/file/threaded_buffered.rb +3 -3
  92. data/lib/ffmprb/filter.rb +4 -1
  93. data/lib/ffmprb/find_silence.rb +5 -2
  94. data/lib/ffmprb/process.rb +5 -3
  95. data/lib/ffmprb/process/input.rb +1 -1
  96. data/lib/ffmprb/process/input/looping.rb +6 -11
  97. data/lib/ffmprb/process/output.rb +9 -6
  98. data/lib/ffmprb/util.rb +5 -3
  99. data/lib/ffmprb/util/proc_vis.rb +1 -1
  100. data/lib/ffmprb/util/thread.rb +6 -5
  101. data/lib/ffmprb/util/threaded_io_buffer.rb +20 -19
  102. data/lib/ffmprb/version.rb +2 -2
  103. data/tmp/output.rb +383 -0
  104. metadata +90 -138
  105. data/.gitignore +0 -10
  106. data/.rspec +0 -4
  107. data/.ruby-version +0 -1
  108. data/.travis.yml +0 -3
  109. data/circle.yml +0 -7
@@ -6,14 +6,43 @@ require 'ffmprb/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'ffmprb'
8
8
  spec.version = Ffmprb::VERSION
9
- spec.authors = ["showbox.com", "Costa Shapiro"]
9
+ spec.authors = ["Costa Shapiro"]
10
10
  spec.email = ['costa@mouldwarp.com']
11
11
 
12
- spec.summary = "ffmprb is your audio/video montage friend, based on https://ffmpeg.org"
12
+ spec.summary = "ffmprb is your audio/video manipulation pal, based on https://ffmpeg.org"
13
13
  spec.description = "A video and audio composing DSL (Damn-Simple Language) and a micro-engine for ffmpeg and ffriends"
14
14
  spec.homepage = Ffmprb::GEM_GITHUB_URL
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ def self.ignore_match(pattern, path)
17
+ path = '/' + path unless path =~ %r'^/'
18
+ if File.directory?(path)
19
+ path += '/' unless path =~ %r'/$'
20
+ end
21
+ if pattern.is_a?(Array)
22
+ pattern
23
+ else
24
+ [pattern]
25
+ end.any? do |pattern|
26
+ pattern = '**/' + pattern unless pattern =~ %r'^/'
27
+ pattern += '**' if pattern =~ %r'/$'
28
+ File.fnmatch(pattern, path)
29
+ end
30
+ end
31
+
32
+ pattern =
33
+ if (ignore_pattern_lines = File.readlines('.gemignore') rescue nil)
34
+ ignore_pattern_lines.map do |line|
35
+ stripped = line.split(/(?<!\\)#/)[0].strip
36
+ stripped unless stripped.empty?
37
+ end.compact
38
+ else
39
+ %w[test/ spec/ features/]
40
+ end
41
+
42
+ # NOTE dotfiles are ignored by .glob
43
+ spec.files = Dir['**/*'].reject{|path| ignore_match pattern, path}
44
+ # TODO:rm spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
45
+
17
46
  spec.bindir = 'exe'
18
47
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
48
  spec.require_paths = ['lib']
@@ -23,15 +52,6 @@ Gem::Specification.new do |spec|
23
52
  # NOTE make it into an optional dependency? Nah for now
24
53
  spec.add_dependency 'thor', '~> 0.19.1'
25
54
 
26
- spec.add_development_dependency 'bundler', '>= 1.11.2'
27
- spec.add_development_dependency 'byebug', '>= 8.2.4'
28
- spec.add_development_dependency 'simplecov', '>= 0.11.2'
29
- spec.add_development_dependency 'guard-rspec', '>= 4.6.5'
30
- spec.add_development_dependency 'guard-bundler', '>= 2.1.0'
31
- spec.add_development_dependency 'rake', '>= 11.1.2'
32
- spec.add_development_dependency 'rmagick', '>= 2.15.4'
33
- spec.add_development_dependency 'ruby-sox', '>= 0.0.3'
34
- spec.add_development_dependency 'firebase', '>= 0.2.6'
35
-
36
- spec.post_install_message = "Have fun with your montage! To enable proc visualisation, install firebase gem and set FFMPRB_PROC_VIS_FIREBASE env." unless Ffmprb::FIREBASE_AVAILABLE
55
+ spec.post_install_message = "Have fun with your a/v! To enable proc visualisation, install firebase gem and set FFMPRB_PROC_VIS_FIREBASE env." unless
56
+ Ffmprb::FIREBASE_AVAILABLE
37
57
  end
@@ -19,7 +19,7 @@ module Ffmprb
19
19
  Process.input_video_fps = nil # NOTE the documented ffmpeg default is 25
20
20
 
21
21
  Process.output_video_resolution = CGA
22
- Process.output_video_fps = 16
22
+ Process.output_video_fps = 16 # NOTE the documented ffmpeg default is 25
23
23
  Process.output_audio_encoder = 'libmp3lame'
24
24
  Process.output_audio_sampling_freq = nil # NOTE Use ffmpeg default by default, specify otherwise e.g. 44100
25
25
 
@@ -25,13 +25,13 @@ module Ffmprb
25
25
  name ||= blk.source_location.map(&:to_s).map{ |s| ::File.basename s.to_s, ::File.extname(s) }.join(':')
26
26
  process = Process.new(name: name, **opts)
27
27
  proc_vis_node process if respond_to? :proc_vis_node # XXX simply include the ProcVis if it makes into a gem
28
- logger.debug "Starting process with #{args} #{opts} in #{blk.source_location}"
28
+ logger.debug{"Starting process with #{args} #{opts} in #{blk.source_location}"}
29
29
 
30
30
  process.instance_exec *args, &blk
31
- logger.debug "Initialized process with #{args} #{opts} in #{blk.source_location}"
31
+ logger.debug{"Initialized process with #{args} #{opts} in #{blk.source_location}"}
32
32
 
33
33
  process.run.tap do
34
- logger.debug "Finished process with #{args} #{opts} in #{blk.source_location}"
34
+ logger.debug{"Finished process with #{args} #{opts} in #{blk.source_location}"}
35
35
  end
36
36
  end
37
37
  alias :action! :process # ;)
@@ -17,27 +17,27 @@ module Ffmprb
17
17
  ->{
18
18
  path = file.respond_to?(:path)? file.path : file
19
19
  mode ||= file.respond_to?(mode)? file.mode.to_s[0] : 'r'
20
- Ffmprb.logger.debug "Trying to open #{path} (for #{mode}-buffering or something)"
20
+ Ffmprb.logger.debug{"Trying to open #{path} (for #{mode}-buffering or something)"}
21
21
  ::File.open(path, mode)
22
22
  }
23
23
  end
24
24
 
25
25
  def create(path)
26
26
  new(path: path, mode: :write).tap do |file|
27
- Ffmprb.logger.debug "Created file with path: #{file.path}"
27
+ Ffmprb.logger.debug{"Created file with path: #{file.path}"}
28
28
  end
29
29
  end
30
30
 
31
31
  def open(path)
32
32
  new(path: path, mode: :read).tap do |file|
33
- Ffmprb.logger.debug "Opened file with path: #{file.path}"
33
+ Ffmprb.logger.debug{"Opened file with path: #{file.path}"}
34
34
  end
35
35
  end
36
36
 
37
37
  def temp(extname)
38
38
  file = create(Tempfile.new(['', extname]))
39
39
  path = file.path
40
- Ffmprb.logger.debug "Created temp file with path: #{path}"
40
+ Ffmprb.logger.debug{"Created temp file with path: #{path}"}
41
41
 
42
42
  return file unless block_given?
43
43
 
@@ -49,7 +49,7 @@ module Ffmprb
49
49
  rescue
50
50
  Ffmprb.logger.warn "#{$!.class.name} removing temp file with path #{path}: #{$!.message}"
51
51
  end
52
- Ffmprb.logger.debug "Removed temp file with path: #{path}"
52
+ Ffmprb.logger.debug{"Removed temp file with path: #{path}"}
53
53
  end
54
54
  end
55
55
 
@@ -69,12 +69,12 @@ module Ffmprb
69
69
  rescue
70
70
  Ffmprb.logger.warn "#{$!.class.name} removing temp file with path #{path}: #{$!.message}"
71
71
  end
72
- Ffmprb.logger.debug "Removed temp file with path: #{path}"
72
+ Ffmprb.logger.debug{"Removed temp file with path: #{path}"}
73
73
  end
74
74
  end
75
75
 
76
76
  def temp_fifo_path(extname)
77
- ::File.join Dir.tmpdir, Dir::Tmpname.make_tmpname('', 'p' + extname)
77
+ ::File.join Dir.tmpdir, "#{rand(2**222)}p#{extname}"
78
78
  end
79
79
 
80
80
  def image?(extname)
@@ -168,7 +168,7 @@ module Ffmprb
168
168
  else
169
169
  FileUtils.remove_entry path
170
170
  end
171
- Ffmprb.logger.debug "Removed file with path: #{path}"
171
+ Ffmprb.logger.debug{"Removed file with path: #{path}"}
172
172
  @path = nil
173
173
  end
174
174
 
@@ -11,7 +11,7 @@ module Ffmprb
11
11
  audio = File.temp('.wav') if audio == true
12
12
  video = File.temp('.png') if video == true
13
13
 
14
- Ffmprb.logger.debug "Snap shooting files, video path: #{video ? video.path : 'NONE'}, audio path: #{audio ? audio.path : 'NONE'}"
14
+ Ffmprb.logger.debug{"Snap shooting files, video path: #{video ? video.path : 'NONE'}, audio path: #{audio ? audio.path : 'NONE'}"}
15
15
 
16
16
  fail Error, "Incorrect output extname (must be image)" unless !video || video.channel?(:video) && !video.channel?(:audio)
17
17
  fail Error, "Incorrect audio extname (must be sound)" unless !audio || audio.channel?(:audio) && !audio.channel?(:video)
@@ -30,7 +30,7 @@ module Ffmprb
30
30
  begin
31
31
  video.unlink if video
32
32
  audio.unlink if audio
33
- Ffmprb.logger.debug "Removed sample files"
33
+ Ffmprb.logger.debug{"Removed sample files"}
34
34
  rescue
35
35
  Ffmprb.logger.warn "#{$!.class.name} removing sample files: #{$!.message}"
36
36
  end
@@ -7,7 +7,7 @@ module Ffmprb
7
7
  def threaded_buffered_fifo(extname='.tmp', reader_open_on_writer_idle_limit: nil, proc_vis: nil)
8
8
  input_fifo_file = temp_fifo(extname)
9
9
  output_fifo_file = temp_fifo(extname)
10
- Ffmprb.logger.debug "Opening #{input_fifo_file.path}>#{output_fifo_file.path} for buffering"
10
+ Ffmprb.logger.debug{"Opening #{input_fifo_file.path}>#{output_fifo_file.path} for buffering"}
11
11
  Util::Thread.new do
12
12
  begin
13
13
  io_buff = Util::ThreadedIoBuffer.new(opener(input_fifo_file, 'r'), opener(output_fifo_file, 'w'), keep_outputs_open_on_input_idle_limit: reader_open_on_writer_idle_limit)
@@ -20,13 +20,13 @@ module Ffmprb
20
20
  ensure
21
21
  Util::Thread.join_children!
22
22
  end
23
- Ffmprb.logger.debug "IoBuffering from #{input_fifo_file.path} to #{output_fifo_file.path} ended"
23
+ Ffmprb.logger.debug{"IoBuffering from #{input_fifo_file.path} to #{output_fifo_file.path} ended"}
24
24
  ensure
25
25
  input_fifo_file.unlink if input_fifo_file
26
26
  output_fifo_file.unlink if output_fifo_file
27
27
  end
28
28
  end
29
- Ffmprb.logger.debug "IoBuffering from #{input_fifo_file.path} to #{output_fifo_file.path} started"
29
+ Ffmprb.logger.debug{"IoBuffering from #{input_fifo_file.path} to #{output_fifo_file.path} started"}
30
30
 
31
31
  [input_fifo_file, output_fifo_file]
32
32
  end
@@ -262,7 +262,10 @@ module Ffmprb
262
262
  end
263
263
 
264
264
  def complex_args(*filters)
265
- ['-filter_complex', filters.join('; ')] unless filters.empty?
265
+ [].tap do |args|
266
+ args << '-filter_complex' << filters.join('; ') unless
267
+ filters.empty?
268
+ end
266
269
  end
267
270
 
268
271
  private
@@ -5,7 +5,7 @@ module Ffmprb
5
5
  # NOTE not for streaming just yet
6
6
  def find_silence(input_file, output_file)
7
7
  path = "#{input_file.path}->#{output_file.path}"
8
- logger.debug "Finding silence (#{path})"
8
+ logger.debug{"Finding silence (#{path})"}
9
9
  silence = []
10
10
  Util.ffmpeg('-i', input_file.path, *find_silence_detect_args, output_file.path).
11
11
  scan(SILENCE_DETECT_REGEX).each do |mark, time|
@@ -25,7 +25,10 @@ module Ffmprb
25
25
  Ffmprb.warn "Unknown silence mark: #{mark}"
26
26
  end
27
27
  end
28
- logger.debug "Found silence (#{path}): [#{silence.map{|t,v| "#{t}: #{v}"}}]"
28
+ logger.debug{
29
+ silence_map = silence.map{|t,v| "#{t}: #{v}"}
30
+ "Found silence (#{path}): [#{silence_map}]"
31
+ }
29
32
  silence
30
33
  end
31
34
 
@@ -39,7 +39,7 @@ module Ffmprb
39
39
  def input_video_options
40
40
  {
41
41
  auto_rotate: input_video_auto_rotate,
42
- fps: input_video_fps
42
+ fps: input_video_fps # TODO seen failing on apng (w/ffmpeg v4.x)
43
43
  }
44
44
  end
45
45
  def input_audio_options
@@ -97,7 +97,10 @@ module Ffmprb
97
97
  end
98
98
  overlay in_over.volume ducked_overlay_volume
99
99
 
100
- Ffmprb.logger.debug "Ducking audio with volumes: {#{ducked_overlay_volume.map{|t,v| "#{t}: #{v}"}.join ', '}}"
100
+ Ffmprb.logger.debug{
101
+ ducked_overlay_volume_map = ducked_overlay_volume.map{|t,v| "#{t}: #{v}"}
102
+ "Ducking audio with volumes: {#{ducked_overlay_volume_map.join ', '}}"
103
+ }
101
104
  end
102
105
 
103
106
  end
@@ -157,7 +160,6 @@ module Ffmprb
157
160
  thr = Util::Thread.new main: !parent do
158
161
  proc_vis_node Thread.current
159
162
  # NOTE yes, an exception can occur anytime, and we'll just die, it's ok, see above
160
- # XXX just to return something -- no apparent practical use
161
163
  cmd = command
162
164
  opts = {limit: limit, timeout: timeout}
163
165
  opts[:ignore_broken_pipes] = ignore_broken_pipes unless ignore_broken_pipes.nil?
@@ -14,7 +14,7 @@ module Ffmprb
14
14
  end
15
15
  end
16
16
 
17
- # XXX check for unknown options
17
+ # TODO! check for unknown options
18
18
 
19
19
  def video_args(video=nil)
20
20
  video = Process.input_video_options.merge(video.to_h)
@@ -60,7 +60,7 @@ module Ffmprb
60
60
  end
61
61
  end
62
62
  cpy_io = File.temp_fifo(src_io.extname)
63
- Ffmprb.logger.debug "(L2) Temporising the raw input (#{src_io.path}) and creating copy (#{cpy_io.path})"
63
+ Ffmprb.logger.debug{"(L2) Temporising the raw input (#{src_io.path}) and creating copy (#{cpy_io.path})"}
64
64
 
65
65
  src_io.threaded_buffered_copy_to @raw.io, cpy_io
66
66
 
@@ -70,9 +70,8 @@ module Ffmprb
70
70
  @raw.process.proc_vis_node dst_io
71
71
 
72
72
  Util::Thread.new "looping input processor" do
73
- # Ffmprb.logger.debug "Processing before looping"
73
+ Ffmprb.logger.debug{"(L3) Pre-processing into (#{dst_io.path})"}
74
74
 
75
- Ffmprb.logger.debug "(L3) Pre-processing into (#{dst_io.path})"
76
75
  Ffmprb.process @_unfiltered, parent: @raw.process do |unfiltered| # TODO limit:
77
76
 
78
77
  inp = input(cpy_io)
@@ -83,10 +82,8 @@ module Ffmprb
83
82
  end
84
83
  end
85
84
 
86
- # Ffmprb.logger.debug "Preprocessed (from #{src_io.path}) looping input: #{dst_io.path}, output: #{io.io.path}, and raw input copy will go through #{buff_raw_io.path} to #{@raw.io.path}..."
87
-
88
85
  buff_ios = (1..times).map{File.temp_fifo intermediate_extname}
89
- Ffmprb.logger.debug "Preprocessed #{dst_io.path} will be teed to #{buff_ios.map(&:path).join '; '}"
86
+ Ffmprb.logger.debug{"Preprocessed #{dst_io.path} will be teed to #{buff_ios.map(&:path).join '; '}"}
90
87
  Util::Thread.new "cloning buffer watcher" do
91
88
  dst_io.threaded_buffered_copy_to(*buff_ios).tap do |io_buff|
92
89
  Util::Thread.join_children!
@@ -94,17 +91,15 @@ module Ffmprb
94
91
  end
95
92
  end
96
93
 
97
- # Ffmprb.logger.debug "Concatenation of #{buff_ios.map(&:path).join '; '} will go to #{@io.io.path} to be fed to this process"
98
-
99
94
  # NOTE additional (filtered, processed and looped) input io
100
95
  aux_io = File.temp_fifo(intermediate_extname)
101
96
 
102
97
  # NOTE (4)
103
98
 
104
99
  Util::Thread.new "looper" do
105
- Ffmprb.logger.debug "Looping #{buff_ios.size} times"
100
+ Ffmprb.logger.debug{"Looping #{buff_ios.size} times"}
106
101
 
107
- Ffmprb.logger.debug "(L4) Looping (#{buff_ios.map &:path}) into (#{aux_io.path})"
102
+ Ffmprb.logger.debug{"(L4) Looping (#{buff_ios.map &:path}) into (#{aux_io.path})"}
108
103
  begin # NOTE may not write its entire output, it's ok
109
104
  Ffmprb.process parent: @raw.process, ignore_broken_pipes: false do
110
105
 
@@ -121,7 +116,7 @@ module Ffmprb
121
116
 
122
117
  # NOTE (1)
123
118
 
124
- Ffmprb.logger.debug "(L1) Creating a new input (#{aux_io.path}) to the process"
119
+ Ffmprb.logger.debug{"(L1) Creating a new input (#{aux_io.path}) to the process"}
125
120
  @raw.process.input(aux_io)
126
121
  end
127
122
 
@@ -84,7 +84,7 @@ module Ffmprb
84
84
  # NOTE Image-Padding to match the target resolution
85
85
  # TODO full screen only at the moment (see exception above)
86
86
 
87
- Ffmprb.logger.debug "#{self} asking for filters of #{curr_reel.reel.io.inspect} video: #{channel(:video)}, audio: #{channel(:audio)}"
87
+ Ffmprb.logger.debug{"#{self} asking for filters of #{curr_reel.reel.io.inspect} video: #{channel(:video)}, audio: #{channel(:audio)}"}
88
88
  @filters.concat(
89
89
  curr_reel.reel.filters_for lbl, video: channel(:video), audio: channel(:audio)
90
90
  )
@@ -151,7 +151,7 @@ module Ffmprb
151
151
  ) if channel?(:audio)
152
152
 
153
153
  segments << new_prev_lbl
154
- Ffmprb.logger.debug "Concatting segments: #{new_prev_lbl} pushed"
154
+ Ffmprb.logger.debug{"Concatting segments: #{new_prev_lbl} pushed"}
155
155
  end
156
156
 
157
157
  if curr_reel.transition
@@ -264,7 +264,7 @@ module Ffmprb
264
264
  end
265
265
  process.proc_vis_edge process, main_av_o, :remove
266
266
  process.proc_vis_edge process, main_av_inter_i
267
- Ffmprb.logger.debug "Re-routed the main audio output (#{main_av_inter_i.path}->...->#{main_av_o.path}) through the process of audio ducking"
267
+ Ffmprb.logger.debug{"Re-routed the main audio output (#{main_av_inter_i.path}->...->#{main_av_o.path}) through the process of audio ducking"}
268
268
 
269
269
  over_a_i, over_a_o = File.threaded_buffered_fifo(Process.intermediate_channel_extname(audio: true, video: false), proc_vis: process)
270
270
  lbl_over = "o#{idx}l#{i}"
@@ -273,10 +273,10 @@ module Ffmprb
273
273
  )
274
274
  @channel_lbl_ios["#{lbl_over}:a"] = over_a_i
275
275
  process.proc_vis_edge process, over_a_i
276
- Ffmprb.logger.debug "Routed and buffering auxiliary output fifos (#{over_a_i.path}>#{over_a_o.path}) for overlay"
276
+ Ffmprb.logger.debug{"Routed and buffering auxiliary output fifos (#{over_a_i.path}>#{over_a_o.path}) for overlay"}
277
277
 
278
278
  inter_i, inter_o = File.threaded_buffered_fifo(intermediate_extname, proc_vis: process)
279
- Ffmprb.logger.debug "Allocated fifos to buffer media (#{inter_i.path}>#{inter_o.path}) while finding silence"
279
+ Ffmprb.logger.debug{"Allocated fifos to buffer media (#{inter_i.path}>#{inter_o.path}) while finding silence"}
280
280
 
281
281
  ignore_broken_pipes_was = process.ignore_broken_pipes # XXX maybe throw an exception instead?
282
282
  process.ignore_broken_pipes = true # NOTE audio ducking process may break the overlay pipe
@@ -285,7 +285,10 @@ module Ffmprb
285
285
  process.proc_vis_edge main_av_inter_o, inter_i # XXX mark it better
286
286
  silence = Ffmprb.find_silence(main_av_inter_o, inter_i)
287
287
 
288
- Ffmprb.logger.debug "Audio ducking with silence: [#{silence.map{|s| "#{s.start_at}-#{s.end_at}"}.join ', '}]"
288
+ Ffmprb.logger.debug{
289
+ silence_map = silence.map{|s| "#{s.start_at}-#{s.end_at}"}
290
+ "Audio ducking with silence: [#{silence_map.join ', '}]"
291
+ }
289
292
 
290
293
  Process.duck_audio inter_o, over_a_o, silence, main_av_o,
291
294
  process_options: {parent: process, ignore_broken_pipes: ignore_broken_pipes_was, timeout: process.timeout},
@@ -18,8 +18,10 @@ module Ffmprb
18
18
  sh *ffprobe_cmd, *args, limit: limit, timeout: timeout
19
19
  end
20
20
 
21
+ # TODO warn on broken pipes incompatibility with 4.x or something
21
22
  def ffmpeg(*args, limit: nil, timeout: cmd_timeout, ignore_broken_pipes: true)
22
- args = ['-loglevel', 'debug'] + args if Ffmprb.ffmpeg_debug
23
+ args = ['-loglevel', 'debug'] + args if
24
+ Ffmprb.ffmpeg_debug
23
25
  sh *ffmpeg_cmd, *args, output: :stderr, limit: limit, timeout: timeout, ignore_broken_pipes: ignore_broken_pipes
24
26
  end
25
27
 
@@ -42,7 +44,7 @@ module Ffmprb
42
44
  value = wait_thr.value
43
45
  status = value.exitstatus # NOTE blocking
44
46
  if status != 0
45
- if value.signaled? && value.termsig == Signal.list['PIPE']
47
+ if value.signaled? && value.termsig == Signal.list['PIPE'] # TODO! this doesn't seem to work for ffmpeg 4.x (it ignores SIGPIPEs)
46
48
  if ignore_broken_pipes
47
49
  Ffmprb.logger.info "Ignoring broken pipe: #{cmd_str}"
48
50
  else
@@ -54,7 +56,7 @@ module Ffmprb
54
56
  end
55
57
  end
56
58
  end
57
- Ffmprb.logger.debug "FINISHED: #{cmd_str}"
59
+ Ffmprb.logger.debug{"FINISHED: #{cmd_str}"}
58
60
 
59
61
  Thread.join_children! limit, timeout: timeout
60
62
 
@@ -137,7 +137,7 @@ module Ffmprb
137
137
  @proc_vis_firebase_client =
138
138
  if proc_vis_firebase
139
139
  url = "https://#{proc_vis_firebase}.firebaseio.com/proc/"
140
- Ffmprb.logger.debug "Connecting to #{url}"
140
+ Ffmprb.logger.debug{"Connecting to #{url}"}
141
141
  begin
142
142
  Firebase::Client.new(url).tap do
143
143
  Ffmprb.logger.info "Connected to #{url}"
@@ -42,12 +42,13 @@ module Ffmprb
42
42
  attr_reader :name
43
43
 
44
44
  def initialize(name="some", main: false, &blk)
45
+ orig_caller = caller
45
46
  @name = name
46
47
  @parent = Thread.current
47
48
  @live_children = []
48
49
  @children_mon = Monitor.new
49
50
  @dead_children_q = Queue.new
50
- Ffmprb.logger.debug "about to launch #{name}"
51
+ Ffmprb.logger.debug{"about to launch #{name}"}
51
52
  sync_q = Queue.new
52
53
  super() do
53
54
  @parent.proc_vis_node self if @parent.respond_to? :proc_vis_node
@@ -57,10 +58,10 @@ module Ffmprb
57
58
  Ffmprb.logger.warn "Not the main: true thread run by a not #{self.class.name} thread" unless main
58
59
  end
59
60
  sync_q.enq :ok
60
- Ffmprb.logger.debug "#{name} thread launched"
61
+ Ffmprb.logger.debug{"#{name} thread launched"}
61
62
  begin
62
63
  blk.call.tap do
63
- Ffmprb.logger.debug "#{name} thread done"
64
+ Ffmprb.logger.debug{"#{name} thread done"}
64
65
  end
65
66
  rescue Exception
66
67
  Ffmprb.logger.warn "#{$!.class.name} raised in #{name} thread: #{$!.message}\nBacktrace:\n\t#{$!.backtrace.join("\n\t")}"
@@ -84,7 +85,7 @@ module Ffmprb
84
85
 
85
86
  def child_lives(thr)
86
87
  @children_mon.synchronize do
87
- Ffmprb.logger.debug "picking up #{thr.name} thread"
88
+ Ffmprb.logger.debug{"picking up #{thr.name} thread"}
88
89
  @live_children << thr
89
90
  end
90
91
  proc_vis_edge self, thr
@@ -92,7 +93,7 @@ module Ffmprb
92
93
 
93
94
  def child_dies(thr)
94
95
  @children_mon.synchronize do
95
- Ffmprb.logger.debug "releasing #{thr.name} thread"
96
+ Ffmprb.logger.debug{"releasing #{thr.name} thread"}
96
97
  @dead_children_q.enq thr
97
98
  fail "System Error" unless @live_children.delete thr
98
99
  end