ffmprb 0.12.2 → 0.12.3

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.
@@ -8,7 +8,7 @@ VIDEO_OPT = {resolution: Ffmprb::HD_1080p, fps: 30}
8
8
 
9
9
 
10
10
  # XXX
11
- def dura_to_sec(dura_str)
11
+ def dura_to(dura_str)
12
12
  dura_str.split(':').reverse.each_with_index.reduce(0) do |sec, (ns, i)|
13
13
  sec + ns.to_i*(60**i)
14
14
  end
@@ -90,6 +90,7 @@ end
90
90
 
91
91
  channel = ARGV.shift || 'default'
92
92
 
93
+ # XXX too complicated? maybe 3 scripts instead?
93
94
  abort "USAGE: gop-raw-cut-you-HD60.rb [CHANNEL]" unless
94
95
  ARGV.empty?
95
96
 
@@ -22,9 +22,9 @@ def google_youtube(cb_uri, user_id, &blk)
22
22
  Google::Apis::YoutubeV3::AUTH_YOUTUBE,
23
23
  Google::Auth::Stores::FileTokenStore.new(file: GOOGLE_CREDENTIAL_STORE)
24
24
  )
25
- youtube.client_options.send_timeout_sec =
26
- youtube.client_options.open_timeout_sec =
27
- youtube.client_options.read_timeout_sec = YOUTUBE_TIMEOUT_SEC
25
+ youtube.client_options.send_timeout =
26
+ youtube.client_options.open_timeout =
27
+ youtube.client_options.read_timeout = YOUTUBE_TIMEOUT
28
28
  youtube.authorization =
29
29
  if (credentials = authorizer.get_credentials(user_id))
30
30
  credentials
data/ffmprb.gemspec CHANGED
@@ -47,6 +47,8 @@ Gem::Specification.new do |spec|
47
47
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
48
48
  spec.require_paths = ['lib']
49
49
 
50
+ spec.required_ruby_version = '>= 2.6' # TODO check 3.X
51
+
50
52
  # NOTE I'm not happy with this dependency, and there's nothing crossplatform (= for windoze too) at the moment
51
53
  spec.add_dependency 'mkfifo', '~> 0.1.1'
52
54
  # NOTE make it into an optional dependency? Nah for now
@@ -2,8 +2,11 @@ module Ffmprb
2
2
 
3
3
  class File
4
4
 
5
+ AUDIO_SAMPLE_MIN = 0.5
6
+
5
7
  def sample(
6
8
  at: 0.01,
9
+ duration: 0,
7
10
  video: true,
8
11
  audio: true,
9
12
  &blk
@@ -11,15 +14,22 @@ module Ffmprb
11
14
  audio = File.temp('.wav') if audio == true
12
15
  video = File.temp('.png') if video == true
13
16
 
14
- Ffmprb.logger.debug{"Snap shooting files, video path: #{video ? video.path : 'NONE'}, audio path: #{audio ? audio.path : 'NONE'}"}
17
+ Ffmprb.logger.debug{"Snap shooting files, video: #{video && video.path}, audio: #{audio && audio.path}"}
15
18
 
16
- fail Error, "Incorrect output extname (must be image)" unless !video || video.channel?(:video) && !video.channel?(:audio)
17
- fail Error, "Incorrect audio extname (must be sound)" unless !audio || audio.channel?(:audio) && !audio.channel?(:video)
18
- fail Error, "Can sample either video OR audio UNLESS a block is given" unless block_given? || !!audio != !!video
19
+ fail Error, "Incorrect output extname (must be image)" unless
20
+ !video || video.channel?(:video) && !video.channel?(:audio)
21
+ fail Error, "Incorrect audio extname (must be sound)" unless
22
+ !audio || audio.channel?(:audio) && !audio.channel?(:video)
23
+ fail Error, "Can sample either video OR audio UNLESS a block is given" unless
24
+ block_given? || !!audio != !!video
25
+ fail Error, "Can sample video just for 0 sec (an image snapshot)" unless
26
+ !video || duration == 0
19
27
 
20
28
  cmd = %W[-i #{path}]
21
29
  cmd.concat %W[-deinterlace -an -ss #{at} -vframes 1 #{video.path}] if video
22
- cmd.concat %W[-vn -ss #{at} -t 1 #{audio.path}] if audio
30
+ audio_duration = [AUDIO_SAMPLE_MIN, duration].max
31
+ audio_at = [0, at - audio_duration / 2].max
32
+ cmd.concat %W[-vn -ss #{audio_at} -t #{audio_duration} #{audio.path}] if audio
23
33
  Util.ffmpeg *cmd
24
34
 
25
35
  return video || audio unless block_given?
@@ -42,7 +52,5 @@ module Ffmprb
42
52
  def sample_audio(*audio, at: 0.01, &blk)
43
53
  sample at: at, video: false, audio: (audio.first || true), &blk
44
54
  end
45
-
46
55
  end
47
-
48
56
  end
data/lib/ffmprb/filter.rb CHANGED
@@ -304,10 +304,18 @@ module Ffmprb
304
304
  end
305
305
 
306
306
 
307
- def complex_args(*filters)
308
- [].tap do |args|
309
- args << '-filter_complex' << filters.join('; ') unless
310
- filters.empty?
307
+ def complex_args(*filters, script_file: nil)
308
+ if filters.empty?
309
+ []
310
+ else
311
+ filter_complex_opt = filters.join('; ')
312
+ if script_file
313
+ script_file.write filter_complex_opt
314
+ script_file.close
315
+ ['-filter_complex_script', script_file.path]
316
+ else
317
+ ['-filter_complex', filter_complex_opt]
318
+ end
311
319
  end
312
320
  end
313
321
 
@@ -25,6 +25,11 @@ module Ffmprb
25
25
  # Doing nothing
26
26
  unfiltered.filters_for lbl, video: video, audio: audio
27
27
  end
28
+
29
+
30
+ def channel(medium)
31
+ io.channel medium
32
+ end
28
33
  end
29
34
  end
30
35
  end
@@ -56,11 +56,7 @@ module Ffmprb
56
56
  ]
57
57
  end
58
58
  end
59
-
60
59
  end
61
-
62
60
  end
63
-
64
61
  end
65
-
66
62
  end
@@ -40,8 +40,8 @@ module Ffmprb
40
40
  attr_reader :process
41
41
 
42
42
  def initialize(io, process, video:, audio:)
43
- @io = self.class.resolve(io)
44
43
  @process = process
44
+ @io = self.class.resolve(io)
45
45
  @channels = {
46
46
  video: video && @io.channel?(:video) && OpenStruct.new(video),
47
47
  audio: audio && @io.channel?(:audio) && OpenStruct.new(audio)
@@ -76,18 +76,18 @@ module Ffmprb
76
76
  Filter.copy "#{in_lbl}:v", "#{lbl}:v"
77
77
  end
78
78
  elsif video
79
- fail Error, "No video stream to provide"
79
+ fail Error, "No video stream to provide ('#{io.path}')"
80
80
  end),
81
81
  *(if audio && channel?(:audio)
82
82
  Filter.anull "#{in_lbl}:a", "#{lbl}:a"
83
83
  elsif audio
84
- fail Error, "No audio stream to provide"
84
+ fail Error, "No audio stream to provide ('#{io.path}')"
85
85
  end)
86
86
  ]
87
87
  end
88
88
 
89
89
  def channel?(medium)
90
- io.channel? medium
90
+ !!channel(medium)
91
91
  end
92
92
 
93
93
  def channel(medium)
@@ -1,3 +1,5 @@
1
+ require 'tempfile'
2
+
1
3
  module Ffmprb
2
4
 
3
5
  class Process
@@ -161,11 +163,12 @@ module Ffmprb
161
163
  thr = Util::Thread.new main: !parent do
162
164
  proc_vis_node Thread.current
163
165
  # NOTE yes, an exception can occur anytime, and we'll just die, it's ok, see above
164
- cmd = command
165
- opts = {limit: limit, timeout: timeout}
166
- opts[:ignore_broken_pipes] = ignore_broken_pipes unless ignore_broken_pipes.nil?
167
- Util.ffmpeg(*cmd, **opts).tap do |res|
168
- Util::Thread.join_children! limit, timeout: timeout
166
+ command do |cmd|
167
+ opts = {limit: limit, timeout: timeout}
168
+ opts[:ignore_broken_pipes] = ignore_broken_pipes unless ignore_broken_pipes.nil?
169
+ Util.ffmpeg(*cmd, **opts).tap do |res|
170
+ Util::Thread.join_children! limit, timeout: timeout
171
+ end
169
172
  end
170
173
  proc_vis_node Thread.current, :remove
171
174
  end
@@ -175,23 +178,28 @@ module Ffmprb
175
178
  private
176
179
 
177
180
  def command
178
- input_args + filter_args + output_args
181
+ fail "Miserably" unless
182
+ block_given?
183
+ Tempfile.create do |tmp_file|
184
+ yield input_args(tmp_file) + filter_args(tmp_file) + output_args(tmp_file)
185
+ end
179
186
  end
180
187
 
181
- def input_args
182
- filter_args # NOTE must run first
188
+ def input_args(script_file=nil)
189
+ filter_args script_file # NOTE must run first
183
190
  @input_args ||= @inputs.map(&:args).reduce(:+)
184
191
  end
185
192
 
186
- # NOTE must run first
187
- def filter_args
193
+ # NOTE must run first (which is excusable just because it's private)
194
+ def filter_args(script_file=nil)
188
195
  @filter_args ||= Filter.complex_args(
189
- @outputs.map(&:filters).reduce :+
196
+ *@outputs.map(&:filters).reduce(:+),
197
+ script_file: script_file
190
198
  )
191
199
  end
192
200
 
193
- def output_args
194
- filter_args # NOTE must run first
201
+ def output_args(script_file=nil)
202
+ filter_args script_file # NOTE must run first
195
203
  @output_args ||= @outputs.map(&:args).reduce(:+)
196
204
  end
197
205
 
data/lib/ffmprb/util.rb CHANGED
@@ -24,12 +24,14 @@ module Ffmprb
24
24
  def ffmpeg(*args, limit: nil, timeout: cmd_timeout, ignore_broken_pipes: true)
25
25
  args = %w[-loglevel debug] + args if
26
26
  Ffmprb.ffmpeg_debug
27
- sh *ffmpeg_cmd, *args,
28
- output: :stderr,
29
- limit: limit,
30
- timeout: timeout,
31
- ignore_broken_pipes: ignore_broken_pipes,
32
- broken_pipe_error_re: FFMPEG_BROKEN_PIPE_ERROR_RE
27
+ sh(
28
+ *ffmpeg_cmd, *args,
29
+ output: :stderr,
30
+ limit: limit,
31
+ timeout: timeout,
32
+ ignore_broken_pipes: ignore_broken_pipes,
33
+ broken_pipe_error_re: FFMPEG_BROKEN_PIPE_ERROR_RE
34
+ )
33
35
  end
34
36
 
35
37
  def sh(*cmd, input: nil, output: :stdout, limit: nil, timeout: cmd_timeout, ignore_broken_pipes: false, broken_pipe_error_re: nil)
@@ -1,6 +1,6 @@
1
1
  module Ffmprb
2
2
 
3
- VERSION = '0.12.2'
3
+ VERSION = '0.12.3'
4
4
 
5
5
  GEM_GITHUB_URL = 'https://github.com/costa/ffmprb'
6
6
 
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.2
4
+ version: 0.12.3
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-02-20 00:00:00.000000000 Z
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mkfifo
@@ -235,7 +235,6 @@ files:
235
235
  - tmp/exp/src/SAM_3132.MP4
236
236
  - tmp/ffmprb-0.11.4.gem
237
237
  - tmp/output.rb
238
- - tmp/rspec_guard_result
239
238
  homepage: https://github.com/costa/ffmprb
240
239
  licenses: []
241
240
  metadata: {}
@@ -248,7 +247,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
248
247
  requirements:
249
248
  - - ">="
250
249
  - !ruby/object:Gem::Version
251
- version: '0'
250
+ version: '2.6'
252
251
  required_rubygems_version: !ruby/object:Gem::Requirement
253
252
  requirements:
254
253
  - - ">="
@@ -1,2 +0,0 @@
1
- 14 examples, 1 failures in 36.6918 seconds
2
- ./spec/ffmprb_spec.rb:485