-
1
require 'rmagick'
-
1
require 'sox'
-
-
1
MIN_VOLUME = -0xFFFF
-
-
1
describe Ffmprb do
-
-
-
1
it 'has a version number' do
-
1
expect(Ffmprb::VERSION).not_to be nil
-
end
-
-
# IMPORTANT NOTE Examples here use static (pre-generated) sample files, but the interface is streaming-oriented
-
# So there's just a hope it all works well with streams, which really must be replaced by appropriate specs
-
-
1
context :process do
-
-
1
around do |example|
-
40
Ffmprb::File.temp('.mp4') do |tf|
-
40
@av_out_file = tf
-
40
Ffmprb::File.temp('.flv') do |tf|
-
40
@av_out_stream_file = tf
-
40
Ffmprb::File.temp('.mp3') do |tf|
-
40
@a_out_file = tf
-
40
example.run
-
end
-
end
-
end
-
end
-
-
1
def check_av_c_gor_at!(at, file: @av_out_file)
-
16
file.sample at: at do |shot, sound|
-
16
check_reddish! pixel_data(shot, 250, 10)
-
16
check_greenish! pixel_data(shot, 250, 110)
-
16
check_note! :C6, wave_data(sound)
-
end
-
end
-
-
1
def check_av_e_bow_at!(at)
-
3
@av_out_file.sample at: at do |shot, sound|
-
3
check_white! pixel_data(shot, 250, 10)
-
3
check_black! pixel_data(shot, 250, 110)
-
3
check_note! :E6, wave_data(sound)
-
end
-
end
-
-
1
def check_av_btn_wtb_at!(at, black: false)
-
8
@av_out_file.sample at: at do |shot, sound|
-
8
pixel = pixel_data(shot, 250, 110)
-
8
wave = wave_data(sound)
-
8
if black
-
2
check_black! pixel
-
2
expect(wave.volume).to eq MIN_VOLUME
-
else
-
6
check_white! pixel
-
6
check_note! :B6, wave
-
6
expect(wave.volume).to be > MIN_VOLUME
-
end
-
end
-
end
-
-
1
def check_black!(pixel)
-
9
expect(channel_max pixel).to be_approximately(0, 0xFFFF)
-
end
-
-
1
def check_white!(pixel)
-
13
expect(channel_min pixel).to be_approximately 0xFFFF
-
end
-
-
1
def check_greenish!(pixel)
-
38
expect(pixel.green).to be > pixel.red
-
38
expect(pixel.green).to be > pixel.blue
-
38
expect(2 * (pixel.red - pixel.blue).abs).to be < (pixel.green - pixel.blue).abs
-
38
expect(2 * (pixel.red - pixel.blue).abs).to be < (pixel.green - pixel.red).abs
-
end
-
-
1
def check_reddish!(pixel)
-
17
expect(pixel.red).to be > pixel.green
-
17
expect(pixel.red).to be > pixel.blue
-
17
expect(2 * (pixel.green - pixel.blue).abs).to be < (pixel.red - pixel.blue).abs
-
17
expect(2 * (pixel.green - pixel.blue).abs).to be < (pixel.red - pixel.green).abs
-
end
-
-
1
def check_note!(note, wave)
-
47
expect(wave.frequency).to be_approximately NOTES[note]
-
end
-
-
-
1
it "should behave like README says it does" do
-
1
flick_mp4 = @av_file_btn_wtb_16.path
-
1
track_mp3 = @a_file_g_16.path
-
1
cine_flv = @av_out_stream_file.path
-
-
1
Ffmprb.process do
-
-
1
in_main = input(flick_mp4)
-
1
output cine_flv, video: {resolution: '1280x720'} do
-
1
roll in_main.crop(0.25).cut(from: 2, to: 5), transition: {blend: 1}
-
1
roll in_main.volume(2).cut(from: 6, to: 16), after: 2, transition: {blend: 1}
-
1
overlay input(track_mp3).volume(0.8)
-
end
-
-
end
-
-
1
expect(@av_out_stream_file.length).to be_approximately 12
-
end
-
-
1
it "should fail on too much inputs" do
-
1
too_much = 99
-
1
expect {
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
34
inps = (0..100).map{input file_input}
-
output file_output do
-
inps.each do |inp|
-
roll inp
-
end
-
end
-
-
end
-
}.to raise_error Ffmprb::Error
-
end
-
-
1
it "should fail on unknown options" do
-
1
expect {
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file, magic: :yes_please!) do |file_input, file_output|
-
-
output file_output do
-
lay file_input
-
end
-
-
end
-
}.to raise_error ArgumentError
-
end
-
-
1
it "should transcode" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output, video: {resolution: Ffmprb::HD_720p, fps: 30}) do
-
1
roll in1
-
end
-
-
end
-
-
1
check_av_c_gor_at! 1
-
1
expect(@av_out_file.resolution).to eq Ffmprb::HD_720p
-
1
expect(@av_out_file.length).to be_approximately 9
-
end
-
-
# TODO! not sure how to deal with this, apng's are bad at metadata (e.g. fps)
-
1
xdescribe "video only (no audio)" do
-
-
1
around do |example|
-
Ffmprb::File.temp_fifo '.apng' do |tmp_papng|
-
-
thr = Thread.new do
-
Ffmprb::Util.ffmpeg '-filter_complex', 'color=white:d=2:r=25', tmp_papng.path
-
end
-
-
@v_in_fifo = tmp_papng
-
-
begin
-
example.run
-
ensure
-
thr.join
-
end
-
end
-
end
-
-
1
it "should transcode with defaults (no audio track)" do
-
Ffmprb.process(@v_in_fifo, @av_out_file) do |fifo_input, file_output|
-
-
in1 = input(fifo_input, video: {fps: 25})
-
output(file_output, audio: false) do
-
roll in1
-
end
-
-
end
-
-
expect(@av_out_file.length).to be_approximately 2
-
-
@av_out_file.sample at: 0.5, audio: false do |image|
-
check_white! pixel_data(image, 250, 110)
-
end
-
expect {
-
@av_out_file.sample at: 0.5, video: false do |sound|
-
expect(false).to be_truthy
-
end
-
}.to raise_error Ffmprb::Error
-
end
-
-
1
xit "should transcode with defaults (silence)" do
-
Ffmprb.process(@v_in_fifo, @av_out_file) do |fifo_input, file_output|
-
-
in1 = input(fifo_input, video: {fps: 25})
-
output(file_output) do
-
roll in1
-
end
-
-
end
-
-
expect(@av_out_file.length).to be_approximately 2
-
@av_out_file.sample at: 0.5 do |image, sound|
-
check_white! pixel_data(image, 250, 110)
-
expect(wave_data(sound).volume).to eq MIN_VOLUME
-
end
-
end
-
-
end
-
-
1
it "should partially support multiple outputs" do
-
1
Ffmprb::File.temp('.mp4') do |another_av_out_file|
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output1|
-
-
1
in1 = input(file_input)
-
1
output(file_output1, video: {resolution: Ffmprb::HD_720p, fps: 30}) do
-
1
roll in1.cut(to: 6)
-
end
-
1
output(another_av_out_file, video: {resolution: Ffmprb::HD_720p, fps: 30}) do
-
1
roll in1
-
end
-
-
end
-
-
1
check_av_c_gor_at! 1
-
1
check_av_c_gor_at! 1, file: another_av_out_file
-
1
expect(@av_out_file.resolution).to eq Ffmprb::HD_720p
-
1
expect(another_av_out_file.resolution).to eq Ffmprb::HD_720p
-
1
expect(@av_out_file.length).to be_approximately 6
-
1
expect(another_av_out_file.length).to be_approximately 9
-
end
-
end
-
-
1
it "should ignore broken pipes (or not)" do
-
1
[[:to, false, Ffmprb::Error], [:not_to, true, nil]].each do |to_not_to, ignore_broken_pipes, error|
-
2
Ffmprb::File.temp_fifo('.flv') do |av_pipe|
-
2
Thread.new do
-
begin
-
2
tmp = File.open(av_pipe.path, 'r')
-
2
tmp.read(1)
-
ensure
-
2
tmp.close if tmp
-
end
-
end
-
-
2
expect do
-
2
Ffmprb.process(@av_file_e_bow_9, ignore_broken_pipes: ignore_broken_pipes) do |file_input|
-
-
2
in1 = input(file_input)
-
2
output(av_pipe, video: {resolution: Ffmprb::HD_1080p, fps: 60}) do
-
2
roll in1.loop
-
end
-
-
end
-
end.send to_not_to, raise_error(*error)
-
end
-
end
-
end
-
-
1
it "should parse path arguments (and transcode)" do
-
1
Ffmprb.process(@av_file_e_bow_9.path, @av_out_file.path) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1
-
end
-
-
end
-
-
1
check_av_e_bow_at! 1
-
1
expect(@av_out_file.resolution).to eq Ffmprb::CGA
-
1
expect(@av_out_file.length).to be_approximately 9
-
end
-
-
1
it "should concat" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1
-
1
roll in1
-
end
-
-
end
-
-
1
check_av_c_gor_at! 2
-
1
check_av_c_gor_at! 8
-
1
expect(@av_out_file.length).to be_approximately 18
-
end
-
-
1
it "should loop" do
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size.tap do |default|
-
begin
-
# NOTE to check for excessive memory consumption during looping etc
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size = 1024
-
-
1
Ffmprb.process(@av_file_btn_wtb_16, @av_out_stream_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1
-
end
-
-
end
-
-
1
expect(@av_out_stream_file.length).to be_approximately 16
-
-
1
Ffmprb.process(@av_out_stream_file, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1.cut(to: 12).loop.cut(to: 47)
-
end
-
end
-
-
1
check_av_btn_wtb_at! 2
-
1
check_av_btn_wtb_at! 6, black: true
-
1
check_av_btn_wtb_at! 10
-
1
check_av_btn_wtb_at! 14
-
1
check_av_btn_wtb_at! 18, black: true
-
1
check_av_btn_wtb_at! 45
-
-
1
expect(@av_out_file.length).to be_approximately 47
-
ensure
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size = default
-
end
-
end
-
end
-
-
1
it "should roll reels after specific time (cutting previous reels)" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_file_btn_wtb_16, @av_out_file) do |file_input, file_input_2, file_output|
-
-
1
in1 = input(file_input)
-
1
in2 = input(file_input_2)
-
1
output(file_output) do
-
1
roll in1
-
1
roll in2, after: 3
-
end
-
-
end
-
-
1
check_av_c_gor_at! 2
-
1
check_av_btn_wtb_at! 4
-
1
expect(@av_out_file.length).to be_approximately 19
-
end
-
-
1
it "should roll reels after specific time (even the first one, adding blanks in the beginning)" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1, after: 3
-
end
-
-
end
-
-
1
check_av_c_gor_at! 4
-
1
expect(@av_out_file.length).to be_approximately 12
-
end
-
-
-
1
[12, 21].each do |duration|
-
2
it "should cut to precise duration (total 12 <=> cut after #{duration})" do
-
2
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
2
in1 = input(file_input)
-
2
output(file_output) do
-
2
roll in1
-
2
roll in1.cut to: (duration - file_input.length)
-
end
-
-
end
-
-
2
check_av_c_gor_at! 5
-
2
check_av_c_gor_at! 7
-
2
expect(@av_out_file.length).to be_approximately duration
-
end
-
end
-
-
1
it "should crop segments" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1.crop(0.25)
-
1
roll in1
-
1
roll in1.crop(width: 0.25, height: 0.25)
-
1
roll in1.crop(left: 0, top: 0, width: 0.25, height: 0.25)
-
end
-
-
end
-
-
1
@av_out_file.sample at: 5 do |snap, sound|
-
1
check_greenish! pixel_data(snap, 100, 10)
-
1
check_note! :C6, wave_data(sound)
-
end
-
1
check_av_c_gor_at! 14
-
1
@av_out_file.sample at: 23 do |snap, sound|
-
1
check_greenish! pixel_data(snap, 100, 10)
-
1
check_note! :C6, wave_data(sound)
-
end
-
1
@av_out_file.sample at: 32 do |snap, sound|
-
1
check_reddish! pixel_data(snap, 100, 10)
-
1
check_note! :C6, wave_data(sound)
-
end
-
end
-
-
1
it "should fail cropping segments unreasonably" do
-
1
expect do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
1
output(file_output) do
-
1
roll input(file_input).crop 0.5
-
end
-
end
-
end.to raise_error Ffmprb::Error
-
end
-
-
1
it "should cut and crop segments" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1.crop(0.25).cut(to: 3)
-
1
roll in1
-
end
-
end
-
-
1
@av_out_file.sample at: 2 do |snap, sound|
-
1
check_greenish! pixel_data(snap, 100, 10)
-
1
check_note! :C6, wave_data(sound)
-
end
-
1
check_av_c_gor_at! 4
-
1
expect(@av_out_file.length).to be_approximately 12
-
end
-
-
1
it "should cut and pace down segments" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_file_e_bow_9, @av_out_file) do |gor_file_input, bow_file_input, file_output|
-
-
1
in1 = input(gor_file_input)
-
1
in2 = input(bow_file_input)
-
1
output(file_output) do
-
1
roll in1.cut(to: 3).pace(0.5)
-
1
roll in2
-
end
-
end
-
-
1
check_av_c_gor_at! 5 # TODO sound wat?
-
1
check_av_e_bow_at! 7
-
1
expect(@av_out_file.length).to be_approximately 15
-
end
-
-
1
it "should cut and pace up segments" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |gor_file_input, file_output|
-
-
1
in1 = input(gor_file_input)
-
1
output(file_output) do
-
1
roll in1.pace(3).cut(from: 1)
-
end
-
end
-
-
1
expect(@av_out_file.length).to be_approximately 2
-
end
-
-
# TODO might be insufficient
-
1
it "should cut segments in any order" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |file_input, file_output|
-
-
1
in1 = input(file_input)
-
1
output(file_output) do
-
1
roll in1.cut(from: 1)
-
1
roll in1.crop(0.25).cut(to: 5)
-
end
-
-
end
-
-
1
check_av_c_gor_at! 1
-
1
@av_out_file.sample at: 9 do |snap, sound|
-
1
check_greenish! pixel_data(snap, 100, 10)
-
1
check_note! :C6, wave_data(sound)
-
end
-
1
expect(@av_out_file.length).to be_approximately 13
-
end
-
-
1
it "should reverse segments etc" do
-
1
Ffmprb::File.temp_fifo('.flv') do |av_pipe|
-
1
Ffmprb::Util::Thread.new do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_file_e_bow_9, av_pipe) do |gor_file_input, bow_file_input, stream_output|
-
-
1
in1 = input(gor_file_input)
-
1
in2 = input(bow_file_input)
-
1
output(stream_output) do
-
1
roll in1.cut(to: 3).pace(0.5)
-
# NOTE a (very) basic 'pp' test
-
1
roll in2.cut(from: 1, to: 11).pp # NOTE a little padding
-
end
-
end
-
end
-
1
Ffmprb.process(av_pipe, @av_out_file) do |stream_input, file_output|
-
-
1
in1 = input(stream_input)
-
1
output(file_output) do
-
1
roll in1.reverse
-
end
-
end
-
end
-
-
# NOTE the `pp` made me change the 'bow' check to be approximate
-
1
check_av_e_bow_at! 7
-
1
check_av_c_gor_at! 11
-
1
expect(@av_out_file.length).to be_approximately 16
-
end
-
-
1
it "should change volume and mute" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |av_i, av_o|
-
1
in1 = input(av_i)
-
1
output(av_o) do
-
1
roll in1.cut(to: 4)
-
1
roll in1.cut(to: 4).mute
-
1
roll in1.cut(to: 4).volume(0.5)
-
end
-
end
-
-
1
expect(
-
3
[5, 9, 1].map{|s| wave_data(@av_out_file.sample_audio at: s).volume}
-
).to be_ascending
-
end
-
-
1
it "should modulate volume" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_out_file) do |av_i, av_o|
-
1
in1 = input(av_i)
-
1
output(av_o) do
-
1
roll in1.cut(to: 3)
-
1
roll in1.volume(1.9 => 0, 4.1 => 0, 6 => 0.5, 7.9 => 1)
-
end
-
end
-
-
8
volume_at = ->(sec){wave_data(@av_out_file.sample_audio at: sec).volume}
-
-
1
expect(volume_at.call 0.1).to be_approximately volume_at.call(11)
-
1
expect(
-
[4, 3.75, 3.5].map(&volume_at)
-
).to be_ascending
-
1
expect(volume_at.call 5).to eq volume_at.call 6
-
end
-
-
1
it "should detect silence and pass input to output" do
-
1
silence = Ffmprb.find_silence(@av_file_btn_wtb_16, @av_out_file)
-
1
expect(silence.length).to eq 2
-
1
prev_silent_end_at = 0
-
1
silence.each do |silent|
-
2
@av_out_file.sample at: silent.start_at + 1 do |image, sound|
-
2
expect(wave_data(sound).volume).to eq MIN_VOLUME
-
2
check_black! pixel_data(image, 100, 100)
-
end
-
2
@av_out_file.sample at: (prev_silent_end_at + silent.start_at)/2 do |image, sound|
-
2
expect(wave_data(sound).volume).to be > MIN_VOLUME
-
2
check_white! pixel_data(image, 100, 100)
-
end
-
2
prev_silent_end_at = silent.end_at
-
end
-
end
-
-
1
context "media" do
-
-
13
let(:m_input) {{video: @v_file_6, audio: @a_file_g_16}}
-
13
let(:m_output_extname) {{video: '.y4m', audio: '.wav'}}
-
-
medium_params = {
-
1
video: {},
-
audio: {encoder: nil}
-
}
-
1
[[:video, :audio], [:audio, :video]].each do |medium, not_medium|
-
[
-
2
lambda do |av_file_input, m_file_input, m_file_output| ##1
-
2
in1 = input(av_file_input)
-
2
output(m_file_output, medium => medium_params[medium], not_medium => false) do
-
2
roll in1.cut(from: 3, to: 5)
-
2
roll in1.cut(from: 3, to: 5)
-
end
-
end,
-
lambda do |av_file_input, m_file_input, m_file_output| ##2
-
2
in1 = input(av_file_input)
-
2
output(m_file_output, medium => medium_params[medium]) do
-
2
roll in1.send(medium).cut(from: 3, to: 5)
-
2
roll in1.send(medium).cut(from: 3, to: 5)
-
end
-
end,
-
lambda do |av_file_input, m_file_input, m_file_output| ##3
-
2
in1 = input(av_file_input)
-
2
output(m_file_output, medium => medium_params[medium]) do
-
2
roll in1.cut(from: 3, to: 5)
-
2
roll in1.cut(from: 3, to: 5)
-
end
-
end,
-
lambda do |av_file_input, m_file_input, m_file_output| ##4
-
2
in1 = input(m_file_input)
-
2
output(m_file_output, medium => medium_params[medium], not_medium => false) do
-
2
roll in1.cut(from: 3, to: 5)
-
2
roll in1.cut(from: 3, to: 5)
-
end
-
end,
-
lambda do |av_file_input, m_file_input, m_file_output| ##5
-
2
in1 = input(m_file_input)
-
2
output(m_file_output, medium => medium_params[medium]) do
-
2
roll in1.send(medium).cut(from: 3, to: 5)
-
2
roll in1.send(medium).cut(from: 3, to: 5)
-
end
-
end,
-
lambda do |av_file_input, m_file_input, m_file_output| ##6
-
2
in1 = input(m_file_input)
-
2
output(m_file_output, medium => medium_params[medium]) do
-
2
roll in1.cut(from: 3, to: 5)
-
2
roll in1.cut(from: 3, to: 5)
-
end
-
end
-
].each_with_index do |script, i|
-
-
12
it "should work with video only and audio only, as input and as output (#{medium}##{i+1})" do
-
-
12
Ffmprb::File.temp(m_output_extname[medium]) do |m_output|
-
-
12
Ffmprb.process(@av_file_c_gor_9, m_input[medium], m_output, &script)
-
-
12
m_output.sample at: 2.5, medium => true, not_medium => false do |sample|
-
12
case medium
-
when :video
-
6
check_greenish! pixel_data(sample, 100, 100)
-
when :audio
-
12
expect{wave_data(m_output)}.not_to raise_error # NOTE audio format compat. check
-
6
check_note! (i < 3 ? :C6 : :G6), wave_data(sample)
-
end
-
end
-
-
-
12
expect(m_output.length).to be_approximately 4
-
12
expect{
-
12
m_output.sample at: 3, not_medium => true, medium => false
-
}.to raise_error Ffmprb::Error
-
end
-
-
end
-
-
end
-
end
-
end
-
-
1
context "stitching" do
-
-
1
it "should transition between two reels" do
-
1
Ffmprb.process(@av_file_c_gor_9, @av_file_e_bow_9, @av_out_file) do |input1, input2, output1|
-
-
1
in1, in2 = input(input1), input(input2)
-
1
output(output1) do
-
1
lay in1.crop(0.25), transition: {blend: 3}
-
1
lay in2.crop(left: 0, top: 0, width: 0.1, height: 0.1).cut(to: 8), after: 6, transition: {blend: 2}
-
# TODO (see below): fin transition: {blend: 4}
-
end
-
-
end
-
-
1
last_green = nil
-
1
last_volume = nil
-
# NOTE should transition from black+silent to green+C6 in 3 secs
-
1
times = [0.1, 1.1, 2.1, 3.1, 4.1]
-
1
times.each do |at|
-
5
@av_out_file.sample at: at do |snap, sound|
-
5
pixel = pixel_data(snap, 100, 100)
-
5
check_greenish! pixel
-
5
if last_green
-
4
if at == times[-1]
-
1
expect(pixel.green).to eq last_green
-
else
-
3
expect(pixel.green).to be > last_green
-
end
-
end
-
5
last_green = pixel.green
-
-
5
wave = wave_data(sound)
-
5
check_note! :C6, wave
-
5
if last_volume
-
4
if at == times[-1]
-
1
expect(wave.volume).to be_approximately last_volume
-
else
-
3
expect(wave.volume).to be > last_volume
-
end
-
end
-
5
last_volume = wave.volume
-
end
-
end
-
-
1
last_red = nil
-
1
last_frequency = nil
-
# NOTE should transition from green+C6 to white+E6 in 2 secs
-
1
times = [4.5, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5]
-
1
times.each do |at|
-
9
@av_out_file.sample at: at do |snap, sound|
-
9
pixel = pixel_data(snap, 100, 100)
-
-
9
check_greenish! pixel unless times[-2..-1].include? at
-
9
expect(0xFFFF - pixel.red).to be_approximately (0xFFFF - pixel.blue)
-
-
9
if last_red
-
8
if times.values_at(0..2, -1).include? at
-
3
expect(pixel.red).to eq last_red
-
else
-
5
expect(pixel.red).to be > last_red
-
end
-
end
-
9
last_red = pixel.red
-
-
9
wave = wave_data(sound)
-
-
9
if times[0..1].include? at
-
2
check_note! :C6, wave
-
7
elsif times[-2..-1].include? at
-
2
check_note! :E6, wave
-
else
-
5
expect(wave.frequency).to be > last_frequency
-
end
-
9
last_frequency = wave.frequency
-
end
-
end
-
-
# NOTE should transition from white+E6 to black+silent in 4 secs
-
# TODO times = [10.9, 11.9, 12.9]
-
-
1
expect(@av_out_file.length).to be_approximately 14
-
end
-
-
1
it "should run an external effect tool for a transition"
-
-
end
-
-
1
context :audio_overlay do
-
-
1
it "should overlay sound with volume" do
-
1
Ffmprb.process(@av_file_btn_wtb_16, @a_file_g_16, @av_out_file) do |input1, input2, output1|
-
-
1
in1 = input(input1)
-
1
in2 = input(input2)
-
1
output(output1) do
-
1
lay in1.volume(0 => 0.5, 4 => 0.5, 5 => 1)
-
1
overlay in2.cut(to: 5).volume(2.0 => 0, 4.0 => 1)
-
end
-
-
end
-
-
volume_first =
-
1
wave_data(@av_out_file.sample at: 0, video: false) do |sound|
-
expect(sound.frequency).to be_between NOTES.G6, NOTES.B6
-
sound.volume
-
end
-
-
1
check_av_btn_wtb_at! 2
-
-
1
wave_data(@av_out_file.sample at: 2, video: false) do |sound|
-
expect(sound.frequency).to be_approximately NOTES.B6
-
expect(sound.volume).to be < volume_first
-
end
-
-
1
wave_data(@av_out_file.sample at: 4, video: false) do |sound|
-
expect(sound.frequency).to be_between NOTES.G6, NOTES.B6
-
expect(sound.volume).to be_approximately volume_first
-
end
-
-
1
expect(
-
wave_data(@av_out_file.sample at: 9, video: false).frequency
-
).to be_approximately NOTES.B6
-
end
-
-
1
it "should loop and duck the overlay sound wrt the main sound" do
-
1
Ffmprb.process(@av_file_btn_wtb_16, @a_file_g_16, @av_out_file) do |input1, input2, output1|
-
-
1
in1 = input(input1)
-
1
in2 = input(input2)
-
1
output(output1, video: {resolution: '800x600'}) do
-
1
lay in1.loop(2), transition: {blend: 1}
-
1
overlay in2.loop, duck: :audio
-
end
-
-
end
-
-
1
@av_out_file.sample at: 2 do |snap, sound|
-
1
check_white! pixel_data(snap, 100, 100)
-
1
expect(wave_data(sound).frequency).to be_between(NOTES.G6, NOTES.B6)
-
end
-
-
1
@av_out_file.sample at: 6 do |snap, sound|
-
1
check_black! pixel_data(snap, 100, 100)
-
1
expect(wave_data(sound).frequency).to be_within(10).of NOTES.G6
-
end
-
-
1
expect(@av_out_file.resolution).to eq '800x600'
-
1
expect(@av_out_file.length).to be_approximately 32
-
end
-
-
1
it "should duck some overlay sound wrt some main sound" do
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size.tap do |default|
-
begin
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size = 1024 # NOTE to check for excessive memory consumption during looping etc
-
-
1
Ffmprb.process @av_file_btn_wtb_16, @a_file_g_16, @av_out_file do |input1, input2, output1|
-
-
1
in1 = input(input1)
-
1
in2 = input(input2)
-
1
output(output1) do
-
1
lay in1.cut(to: 10), transition: {blend: 1}
-
1
overlay in2.cut(from: 4).loop, duck: :audio
-
end
-
-
end
-
-
1
@av_out_file.sample at: 2 do |snap, sound|
-
1
check_white! pixel_data(snap, 100, 100)
-
1
expect(wave_data(sound).frequency).to be_between(NOTES.G6, NOTES.B6)
-
end
-
-
1
@av_out_file.sample at: 6 do |snap, sound|
-
1
check_black! pixel_data(snap, 100, 100)
-
1
expect(wave_data(sound).frequency).to be_within(10).of NOTES.G6
-
end
-
-
1
expect(@av_out_file.length).to be_approximately 10
-
ensure
-
1
Ffmprb::Util::ThreadedIoBuffer.block_size = default
-
end
-
end
-
end
-
-
1
it "should duck some overlay sound wrt some main sound" do
-
1
Ffmprb.process(@a_file_g_16, @a_out_file) do |input1, output1|
-
-
1
in1 = input(input1)
-
1
output(output1) do
-
1
roll in1.cut(from: 4, to: 12), transition: {blend: 1}
-
1
overlay in1, duck: :audio
-
end
-
-
end
-
-
1
expect(@a_out_file.length).to be_approximately(8)
-
-
1
[2, 6].each do |at|
-
2
check_note! :G6, wave_data(@a_out_file.sample_audio at: at)
-
end
-
end
-
-
end
-
-
1
context :samples do
-
-
1
it "should shoot snaps"
-
end
-
-
end
-
-
1
context :info do
-
-
1
it "should return the length of a clip" do
-
1
expect(@av_file_c_gor_9.length).to be_approximately 9
-
end
-
-
end
-
-
1
def pixel_data(snap, x, y)
-
79
Magick::Image.read(snap.path)[0].pixel_color(x, y)
-
end
-
-
1
def wave_data(sound)
-
82
sox_info = Ffmprb::Util.sh(Sox::SOX_COMMAND, sound.path, '-n', 'stat', output: :stderr)
-
-
82
OpenStruct.new.tap do |data|
-
82
data.frequency = $1.to_f if sox_info =~ /Rough\W+frequency:\W*([\d.]+)/
-
82
data.frequency = 0 unless data.frequency && data.frequency > 0
-
82
data.volume = -$1.to_f if sox_info =~ /Volume\W+adjustment:\W*([\d.]+)/
-
82
data.volume ||= MIN_VOLUME
-
end
-
end
-
-
1
def channel_min(pixel)
-
13
[pixel.red, pixel.green, pixel.blue].min
-
end
-
-
1
def channel_max(pixel)
-
9
[pixel.red, pixel.green, pixel.blue].max
-
end
-
-
end