Class: Ffmprb::Process

Inherits:
Object
  • Object
show all
Defined in:
lib/ffmprb/process.rb,
lib/ffmprb/process/input.rb,
lib/ffmprb/process/output.rb,
lib/ffmprb/process/input/cut.rb,
lib/ffmprb/process/input/loud.rb,
lib/ffmprb/process/input/temp.rb,
lib/ffmprb/process/input/cropped.rb,
lib/ffmprb/process/input/looping.rb,
lib/ffmprb/process/input/channeled.rb,
lib/ffmprb/process/input/chain_base.rb

Defined Under Namespace

Classes: Input, Output

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, **opts) ⇒ Process

Returns a new instance of Process.



93
94
95
96
97
98
99
# File 'lib/ffmprb/process.rb', line 93

def initialize(*args, **opts)
  @inputs, @outputs = [], []
  self.timeout = opts.delete(:timeout) || self.class.timeout

  self.ignore_broken_pipe = opts.delete(:ignore_broken_pipe)
  fail Error, "Unknown options: #{opts}"  unless opts.empty?
end

Class Attribute Details

.duck_audio_silent_minObject

Returns the value of attribute duck_audio_silent_min.



7
8
9
# File 'lib/ffmprb/process.rb', line 7

def duck_audio_silent_min
  @duck_audio_silent_min
end

.duck_audio_transition_in_startObject

Returns the value of attribute duck_audio_transition_in_start.



9
10
11
# File 'lib/ffmprb/process.rb', line 9

def duck_audio_transition_in_start
  @duck_audio_transition_in_start
end

.duck_audio_transition_lengthObject

Returns the value of attribute duck_audio_transition_length.



9
10
11
# File 'lib/ffmprb/process.rb', line 9

def duck_audio_transition_length
  @duck_audio_transition_length
end

.duck_audio_transition_out_startObject

Returns the value of attribute duck_audio_transition_out_start.



9
10
11
# File 'lib/ffmprb/process.rb', line 9

def duck_audio_transition_out_start
  @duck_audio_transition_out_start
end

.duck_audio_volume_hiObject

Returns the value of attribute duck_audio_volume_hi.



7
8
9
# File 'lib/ffmprb/process.rb', line 7

def duck_audio_volume_hi
  @duck_audio_volume_hi
end

.duck_audio_volume_loObject

Returns the value of attribute duck_audio_volume_lo.



7
8
9
# File 'lib/ffmprb/process.rb', line 7

def duck_audio_volume_lo
  @duck_audio_volume_lo
end

.input_optionsObject

Returns the value of attribute input_options.



12
13
14
# File 'lib/ffmprb/process.rb', line 12

def input_options
  @input_options
end

.output_audio_encoderObject

Returns the value of attribute output_audio_encoder.



16
17
18
# File 'lib/ffmprb/process.rb', line 16

def output_audio_encoder
  @output_audio_encoder
end

.output_video_fpsObject

Returns the value of attribute output_video_fps.



15
16
17
# File 'lib/ffmprb/process.rb', line 15

def output_video_fps
  @output_video_fps
end

.output_video_resolutionObject

Returns the value of attribute output_video_resolution.



14
15
16
# File 'lib/ffmprb/process.rb', line 14

def output_video_resolution
  @output_video_resolution
end

.timeoutObject

Returns the value of attribute timeout.



18
19
20
# File 'lib/ffmprb/process.rb', line 18

def timeout
  @timeout
end

Instance Attribute Details

#ignore_broken_pipeObject

Returns the value of attribute ignore_broken_pipe.



91
92
93
# File 'lib/ffmprb/process.rb', line 91

def ignore_broken_pipe
  @ignore_broken_pipe
end

#timeoutObject

Returns the value of attribute timeout.



90
91
92
# File 'lib/ffmprb/process.rb', line 90

def timeout
  @timeout
end

Class Method Details

.duck_audio(av_main_i, a_overlay_i, silence, av_main_o, volume_lo: duck_audio_volume_lo, volume_hi: duck_audio_volume_hi, silent_min: duck_audio_silent_min, process_options: {}, video:, audio:) ⇒ Object

NOTE Temporarily, av_main_i/o and not a_main_i/o



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/ffmprb/process.rb', line 45

def duck_audio(av_main_i, a_overlay_i, silence, av_main_o,
  volume_lo: duck_audio_volume_lo,
  volume_hi: duck_audio_volume_hi,
  silent_min: duck_audio_silent_min,
  process_options: {},
  video:,  # NOTE Temporarily, video should not be here
  audio:
  )
  Ffmprb.process **process_options do

    in_main = input(av_main_i)
    in_over = input(a_overlay_i)
    output(av_main_o, video: video, audio: audio) do
      roll in_main

      ducked_overlay_volume = {0.0 => volume_lo}
      silence.each do |silent|
        next  if silent.end_at && silent.start_at && (silent.end_at - silent.start_at) < silent_min

        if silent.start_at
          transition_in_start = silent.start_at + Process.duck_audio_transition_in_start
          ducked_overlay_volume.merge!(
            [transition_in_start, 0.0].max => volume_lo,
            (transition_in_start + Process.duck_audio_transition_length) => volume_hi
          )
        end

        if silent.end_at
          transition_out_start = silent.end_at + Process.duck_audio_transition_out_start
          ducked_overlay_volume.merge!(
            [transition_out_start, 0.0].max => volume_hi,
            (transition_out_start + Process.duck_audio_transition_length) => volume_lo
          )
        end
      end
      overlay in_over.volume ducked_overlay_volume

      Ffmprb.logger.debug "Ducking audio with volumes: {#{ducked_overlay_volume.map{|t,v| "#{t}: #{v}"}.join ', '}}"
    end

  end
end

.intermediate_channel_extname(*media) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
# File 'lib/ffmprb/process.rb', line 20

def intermediate_channel_extname(*media)
  if media == [:video]
    '.y4m'
  elsif media == [:audio]
    '.wav'
  elsif media.sort == [:audio, :video]
    '.flv'
  else
    fail Error, "I don't know how to channel [#{media.join ', '}]"
  end
end

.output_audio_optionsObject



38
39
40
41
42
# File 'lib/ffmprb/process.rb', line 38

def output_audio_options
  {
    encoder: output_audio_encoder
  }
end

.output_video_optionsObject



32
33
34
35
36
37
# File 'lib/ffmprb/process.rb', line 32

def output_video_options
  {
    resolution: output_video_resolution,
    fps: output_video_fps
  }
end

Instance Method Details

#input(io, **opts) ⇒ Object



101
102
103
104
105
# File 'lib/ffmprb/process.rb', line 101

def input(io, **opts)
  Input.new(io, self, **self.class.input_options.merge(opts)).tap do |inp|
    @inputs << inp
  end
end

#input_label(input) ⇒ Object



113
114
115
# File 'lib/ffmprb/process.rb', line 113

def input_label(input)
  @inputs.index input
end

#output(io, video: true, audio: true, &blk) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/ffmprb/process.rb', line 117

def output(io, video: true, audio: true, &blk)
  Output.new(io, self,
    video: channel_params(video, self.class.output_video_options),
    audio: channel_params(audio, self.class.output_audio_options)
  ).tap do |out|
    @outputs << out
    out.instance_exec &blk  if blk
  end
end

#output_index(output) ⇒ Object



127
128
129
# File 'lib/ffmprb/process.rb', line 127

def output_index(output)
  @outputs.index output
end

#run(limit: nil) ⇒ Object

NOTE the one and the only entry-point processing function which spawns threads etc



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/ffmprb/process.rb', line 132

def run(limit: nil)  # TODO (async: false)
  # NOTE this is both for the future async: option and according to
  # the threading policy (a parent death will be noticed and handled by children)
  thr = Util::Thread.new do
    # NOTE yes, an exception can occur anytime, and we'll just die, it's ok, see above
    # XXX just to return something -- no apparent practical use
    cmd = command
    Util.ffmpeg(*cmd, limit: limit, timeout: timeout, ignore_broken_pipe: @ignore_broken_pipe).tap do |res|
      Util::Thread.join_children! limit, timeout: timeout
    end
  end
  thr.value  if thr.join limit  # NOTE should not block for more than limit
end

#temp_input(extname) ⇒ Object

XXX SPEC ME



107
108
109
110
111
# File 'lib/ffmprb/process.rb', line 107

def temp_input(extname)  # XXX SPEC ME
  input(nil).tap do |inp|
    inp.temporise! extname
  end
end