headless-muse 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis/setup.sh +2 -2
- data/README.md +3 -1
- data/headless.gemspec +3 -3
- data/lib/headless/cli_util.rb +15 -4
- data/lib/headless/video/video_recorder.rb +9 -1
- data/spec/cli_util_spec.rb +33 -2
- data/spec/features/capture_video_spec.rb +25 -0
- data/spec/features/headless_spec.rb +13 -0
- data/spec/video_recorder_spec.rb +18 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2bebc3311027182542cd8a5374d6f56074b9954
|
4
|
+
data.tar.gz: 9a26b8fb2b5b68ff99423af6501e2ceca992ec90
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 976b2176d38bc395b96e574e6252a893f4e44df9d9d0920c5f46c542bbe1737b37725fb6f2d060672985fce9e88598bf8892861a6b02e29d0311dd741cb36d56
|
7
|
+
data.tar.gz: 0ee6c18e1b05285179dd1f884896d8fd39b2b496e628042a61237183b8dcdcb660329b1d55eb563337f5a9b2ff3aa21652310811ca21d6d00a375f3a758256c8
|
data/.travis/setup.sh
CHANGED
@@ -3,7 +3,7 @@ case "$FFMPEG_VERSION" in
|
|
3
3
|
2.3)
|
4
4
|
sudo add-apt-repository ppa:archivematica/externals -y
|
5
5
|
sudo apt-get update -q
|
6
|
-
sudo apt-get install ffmpeg
|
6
|
+
sudo apt-get install ffmpeg fluxbox
|
7
7
|
;;
|
8
8
|
|
9
9
|
1.2)
|
@@ -11,5 +11,5 @@ case "$FFMPEG_VERSION" in
|
|
11
11
|
;;
|
12
12
|
*)
|
13
13
|
sudo apt-get update -q
|
14
|
-
sudo apt-get install ffmpeg
|
14
|
+
sudo apt-get install ffmpeg fluxbox
|
15
15
|
esac
|
data/README.md
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
# Headless
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/headless-muse.svg)](http://badge.fury.io/rb/headless-muse)
|
2
3
|
[![Build Status](https://travis-ci.org/pgeraghty/headless.svg?branch=master)](https://travis-ci.org/pgeraghty/headless)
|
3
4
|
[![Coverage Status](https://img.shields.io/coveralls/pgeraghty/headless.svg)](https://coveralls.io/r/pgeraghty/headless?branch=master)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/pgeraghty/headless/badges/gpa.svg)](https://codeclimate.com/github/pgeraghty/headless)
|
4
6
|
|
5
7
|
# This fork
|
6
8
|
|
7
|
-
This fork is the source of the [headless-muse gem]().
|
9
|
+
This fork is the source of the [headless-muse gem](https://rubygems.org/gems/headless-muse).
|
8
10
|
|
9
11
|
## Notes by original author (Leonid Shevtsov)
|
10
12
|
|
data/headless.gemspec
CHANGED
@@ -3,16 +3,16 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.email = 'muse@appsthatcould.be'
|
4
4
|
|
5
5
|
s.name = 'headless-muse'
|
6
|
-
s.version = '1.1.
|
6
|
+
s.version = '1.1.1'
|
7
7
|
s.summary = 'Ruby headless display interface'
|
8
8
|
|
9
9
|
s.description = <<-EOF
|
10
10
|
Headless is a Ruby interface for Xvfb. It allows you to create a headless display straight from Ruby code, hiding some low-level action.
|
11
|
-
It can also capture video and audio via ffmpeg and take screenshots.
|
11
|
+
It can also capture video and audio via ffmpeg (including the latest versions) and take screenshots using ImageMagick.
|
12
12
|
EOF
|
13
13
|
s.requirements = 'Xvfb'
|
14
14
|
s.homepage = 'https://github.com/pgeraghty/headless'
|
15
|
-
s.license = 'MIT'
|
15
|
+
s.license = 'MIT'
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
|
18
18
|
s.add_development_dependency 'rake'
|
data/lib/headless/cli_util.rb
CHANGED
@@ -23,10 +23,8 @@ class Headless
|
|
23
23
|
Process.kill(0, pid)
|
24
24
|
pid
|
25
25
|
rescue Errno::ESRCH
|
26
|
-
|
26
|
+
false
|
27
27
|
end
|
28
|
-
else
|
29
|
-
nil
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
@@ -43,9 +41,10 @@ class Headless
|
|
43
41
|
end
|
44
42
|
|
45
43
|
def self.kill_process(pid_filename, options={})
|
44
|
+
options[:sig] ||= 'TERM'
|
46
45
|
if pid = self.read_pid(pid_filename)
|
47
46
|
begin
|
48
|
-
Process.kill
|
47
|
+
Process.kill options[:sig], pid
|
49
48
|
Process.wait pid if options[:wait]
|
50
49
|
rescue Errno::ESRCH
|
51
50
|
# no such process; assume it's already killed
|
@@ -60,5 +59,17 @@ class Headless
|
|
60
59
|
# pid file already removed
|
61
60
|
end
|
62
61
|
end
|
62
|
+
|
63
|
+
def self.signal_process(pid_filename, signal, options={})
|
64
|
+
if pid = self.read_pid(pid_filename)
|
65
|
+
begin
|
66
|
+
Process.kill signal, pid
|
67
|
+
true
|
68
|
+
rescue Errno::ESRCH
|
69
|
+
# no such process; assume it's already killed
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
63
74
|
end
|
64
75
|
end
|
@@ -58,8 +58,16 @@ class Headless
|
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
def pause
|
62
|
+
CliUtil.signal_process(@pid_file_path, 'STOP')
|
63
|
+
end
|
64
|
+
|
65
|
+
def resume
|
66
|
+
CliUtil.signal_process(@pid_file_path, 'CONT')
|
67
|
+
end
|
68
|
+
|
61
69
|
def stop_and_save(path)
|
62
|
-
CliUtil.kill_process(@pid_file_path, :wait => true)
|
70
|
+
CliUtil.kill_process(@pid_file_path, :wait => true, :sig => 'INT')
|
63
71
|
if File.exists? @tmp_file_path
|
64
72
|
begin
|
65
73
|
FileUtils.mv(@tmp_file_path, path)
|
data/spec/cli_util_spec.rb
CHANGED
@@ -57,9 +57,40 @@ describe Headless::CliUtil do
|
|
57
57
|
subject.class.read_pid('/tmp/.headless_ffmpeg_99.pid').should eq(999999999999)
|
58
58
|
end
|
59
59
|
|
60
|
-
it 'returns
|
60
|
+
it 'returns false after a rescued error when process does not exist' do
|
61
61
|
Process.stub(:kill).and_raise(Errno::ESRCH)
|
62
|
-
subject.class.read_pid('/tmp/.headless_ffmpeg_99.pid').should eq(
|
62
|
+
subject.class.read_pid('/tmp/.headless_ffmpeg_99.pid').should eq(false)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'signal_process' do
|
67
|
+
let(:pidfile) { '/tmp/pid' }
|
68
|
+
let(:fakepid) { 999999999999 }
|
69
|
+
|
70
|
+
before do
|
71
|
+
Process.stub(:kill)
|
72
|
+
File.stub(:read).and_return(fakepid.to_s)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'reads PID file' do
|
76
|
+
#File.should_receive(:read).with(pidfile).and_return('')
|
77
|
+
File.stub(:read).and_return('')
|
78
|
+
subject.class.should_receive(:read_pid).with(pidfile).and_return(nil)
|
79
|
+
subject.class.signal_process(pidfile, 'CONT').should eq(nil)
|
63
80
|
end
|
81
|
+
|
82
|
+
it 'sends signal to process' do
|
83
|
+
Process.should_receive(:kill).with('CONT', fakepid)
|
84
|
+
subject.class.should_receive(:read_pid).with(pidfile).and_return(fakepid)
|
85
|
+
subject.class.signal_process(pidfile, 'CONT').should eq(true)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'returns false after a rescued error when process does not exist' do
|
89
|
+
Process.stub(:kill).and_raise(Errno::ESRCH)
|
90
|
+
subject.class.should_receive(:read_pid).with(pidfile).and_return(fakepid)
|
91
|
+
subject.class.signal_process(pidfile, 'STOP').should eq(false)
|
92
|
+
end
|
93
|
+
|
94
|
+
|
64
95
|
end
|
65
96
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Headless::VideoRecorder do
|
4
|
+
it 'should capture 10s of video on request' do
|
5
|
+
h = Headless.new(:display => 99, :reuse => true, :dimensions => '1280x720x24')
|
6
|
+
|
7
|
+
capture_file = '/tmp/screen-capture-mpeg4.mkv'
|
8
|
+
log = '/tmp/ffmpeg_test.log'
|
9
|
+
|
10
|
+
sleep 5 # give Xvfb some time
|
11
|
+
`DISPLAY=:99 fluxbox > /dev/null 2>&1 &`
|
12
|
+
sleep 3
|
13
|
+
`ffmpeg -f x11grab -r 30 -s 1280x720 -i :99.0 -vcodec mpeg4 -qscale:v 2 -threads 1 -y -t 10 #{capture_file} > #{log} 2>&1`
|
14
|
+
expected_duration =
|
15
|
+
if h.video.guess_ffmpeg_version! > Gem::Version.new(1.2)
|
16
|
+
/time=00:00:10/
|
17
|
+
else
|
18
|
+
/time=10/
|
19
|
+
end
|
20
|
+
expect(File.read log).to match(expected_duration)
|
21
|
+
expect(`ffprobe #{capture_file} 2>&1 | grep Duration`).to match(/Duration: 00:00:10/)
|
22
|
+
`rm #{capture_file}`
|
23
|
+
expect { h.destroy }.not_to raise_error
|
24
|
+
end
|
25
|
+
end if Headless::CliUtil.application_exists?('Xvfb') && Headless::CliUtil.application_exists?('ffmpeg')
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Headless do
|
4
|
+
let(:h) { Headless.new }
|
5
|
+
|
6
|
+
it 'should start Xvfb when instantiated' do
|
7
|
+
expect(h).to be_instance_of(Headless)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should destroy Xvfb when requested' do
|
11
|
+
expect { h.destroy }.not_to raise_error
|
12
|
+
end
|
13
|
+
end if Headless::CliUtil.application_exists?('Xvfb')
|
data/spec/video_recorder_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe Headless::VideoRecorder do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
context
|
35
|
+
context 'stopping, pausing and resuming video recording' do
|
36
36
|
let(:tmpfile) { '/tmp/ci.mov' }
|
37
37
|
let(:filename) { '/tmp/test.mov' }
|
38
38
|
let(:pidfile) { '/tmp/pid' }
|
@@ -45,7 +45,7 @@ describe Headless::VideoRecorder do
|
|
45
45
|
|
46
46
|
describe "using #stop_and_save" do
|
47
47
|
it "stops video recording and saves file" do
|
48
|
-
Headless::CliUtil.should_receive(:kill_process).with(pidfile, :wait => true)
|
48
|
+
Headless::CliUtil.should_receive(:kill_process).with(pidfile, :wait => true, :sig => 'INT')
|
49
49
|
File.should_receive(:exists?).with(tmpfile).and_return(true)
|
50
50
|
FileUtils.should_receive(:mv).with(tmpfile, filename)
|
51
51
|
|
@@ -75,6 +75,22 @@ describe Headless::VideoRecorder do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
describe 'using #pause' do
|
79
|
+
it 'pauses video recording' do
|
80
|
+
Headless::CliUtil.should_receive(:signal_process).with(pidfile, 'STOP')
|
81
|
+
|
82
|
+
expect(subject.pause).to eq(nil)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe 'using #resume' do
|
87
|
+
it 'resumes video recording' do
|
88
|
+
Headless::CliUtil.should_receive(:signal_process).with(pidfile, 'CONT')
|
89
|
+
|
90
|
+
expect(subject.resume).to eq(nil)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
78
94
|
describe '#capture_running?' do
|
79
95
|
it 'returns false unless the PID file exists' do
|
80
96
|
Headless::CliUtil.should_receive(:read_pid).with(pidfile)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: headless-muse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Leonid Shevtsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-08-
|
13
|
+
date: 2014-08-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -56,7 +56,7 @@ dependencies:
|
|
56
56
|
version: '0'
|
57
57
|
description: |2
|
58
58
|
Headless is a Ruby interface for Xvfb. It allows you to create a headless display straight from Ruby code, hiding some low-level action.
|
59
|
-
It can also capture video and audio via ffmpeg and take screenshots.
|
59
|
+
It can also capture video and audio via ffmpeg (including the latest versions) and take screenshots using ImageMagick.
|
60
60
|
email: muse@appsthatcould.be
|
61
61
|
executables: []
|
62
62
|
extensions: []
|
@@ -75,6 +75,8 @@ files:
|
|
75
75
|
- lib/headless/cli_util.rb
|
76
76
|
- lib/headless/video/video_recorder.rb
|
77
77
|
- spec/cli_util_spec.rb
|
78
|
+
- spec/features/capture_video_spec.rb
|
79
|
+
- spec/features/headless_spec.rb
|
78
80
|
- spec/headless_spec.rb
|
79
81
|
- spec/spec_helper.rb
|
80
82
|
- spec/video_recorder_spec.rb
|