ffmpeg-screenrecorder 1.0.0.beta → 1.0.0.beta2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +1 -1
- data/README.md +52 -2
- data/ffmpeg-screenrecorder.gemspec +31 -30
- data/lib/ffmpeg/recorder_options.rb +106 -0
- data/lib/ffmpeg/screenrecorder.rb +75 -111
- data/lib/ffmpeg/windows.rb +18 -0
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e85788e1924b1350003ba607d5cec470878cb2ecc49a5cf53d5508c4604cb38d
|
4
|
+
data.tar.gz: b438f32841d00eb3c6d3b6a996379f61a9c5e1c4a74335729bd6fc725bf23bae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f36dafd064d1363b8dd5c42e39c2b840bc6a68db1cc7d42b8c65a667b78e45140c304a47581350a32913a79e6860f34d82778cb89510ec4c1f5925b35f22ee8f
|
7
|
+
data.tar.gz: 98763086b2b600ee80cc319b0b5a86bd598aa5e561f309c929afc613ae002caccf535ebb0d00050ad1a75380fd2d87f3e44b106dd13304571b2d13b5499f6a88
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
# FFMPEG::Screenrecorder
|
2
2
|
|
3
|
-
Ruby gem to record your computer screen using [FFMPEG](https://www.ffmpeg.org/).
|
3
|
+
Ruby gem to record your computer screen - desktop or specific application/window - using [FFMPEG](https://www.ffmpeg.org/).
|
4
|
+
|
5
|
+
## Support
|
6
|
+
|
7
|
+
Only supports Windows OS as of version `1.0.0-beta2`.
|
4
8
|
|
5
9
|
## Installation
|
6
10
|
|
@@ -20,7 +24,53 @@ Or install it yourself as:
|
|
20
24
|
|
21
25
|
## Usage
|
22
26
|
|
23
|
-
|
27
|
+
##### Record Desktop
|
28
|
+
|
29
|
+
```
|
30
|
+
opts = { output: 'ffmpeg-screenrecorder-output.mp4',
|
31
|
+
input: 'desktop',
|
32
|
+
framerate: 30.0,
|
33
|
+
device: 'gdigrab',
|
34
|
+
log: 'ffmpeg-screenrecorder-log.txt' }
|
35
|
+
@recorder = FFMPEG::Screenrecorder.new(opts)
|
36
|
+
|
37
|
+
# Start recording
|
38
|
+
@recorder.start
|
39
|
+
|
40
|
+
# ... Run tests or whatever you want to record
|
41
|
+
|
42
|
+
# Stop recording
|
43
|
+
@recorder.stop
|
44
|
+
|
45
|
+
# Recording file will be available: ffmpeg-screenrecorder-output.mp4
|
46
|
+
```
|
47
|
+
|
48
|
+
##### Record Specific Application/Window
|
49
|
+
```
|
50
|
+
require 'watir'
|
51
|
+
|
52
|
+
browser = Watir::Browser.new :firefox
|
53
|
+
|
54
|
+
FFMPEG::Screenrecorder.window_titles('firefox') # Name of exe
|
55
|
+
#=> "Mozilla Firefox"
|
56
|
+
|
57
|
+
opts = { output: 'ffmpeg-screenrecorder-firefox.mp4',
|
58
|
+
input: 'Mozilla Firefox',
|
59
|
+
framerate: 30.0,
|
60
|
+
device: 'gdigrab',
|
61
|
+
log: 'ffmpeg-screenrecorder-firefox.txt' }
|
62
|
+
@recorder = FFMPEG::Screenrecorder.new(opts)
|
63
|
+
|
64
|
+
# Start recording
|
65
|
+
@recorder.start
|
66
|
+
|
67
|
+
# ... Run tests or whatever you want to record
|
68
|
+
|
69
|
+
# Stop recording
|
70
|
+
@recorder.stop
|
71
|
+
|
72
|
+
# Recording file will be available: ffmpeg-screenrecorder-output.mp4
|
73
|
+
```
|
24
74
|
|
25
75
|
## Development
|
26
76
|
|
@@ -1,30 +1,31 @@
|
|
1
|
-
lib = File.expand_path('lib', __dir__)
|
2
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
|
4
|
-
Gem::Specification.new do |spec|
|
5
|
-
spec.name = 'ffmpeg-screenrecorder'
|
6
|
-
spec.version = '1.0.0.
|
7
|
-
spec.authors = ['Lakshya Kapoor']
|
8
|
-
spec.email = ['kapoorlakshya@gmail.com']
|
9
|
-
|
10
|
-
spec.summary = 'Record your computer screen using ffmpeg via Ruby.'
|
11
|
-
spec.description = '
|
12
|
-
|
13
|
-
spec.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency '
|
25
|
-
spec.add_development_dependency '
|
26
|
-
spec.add_development_dependency '
|
27
|
-
|
28
|
-
|
29
|
-
spec.add_runtime_dependency '
|
30
|
-
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'ffmpeg-screenrecorder'
|
6
|
+
spec.version = '1.0.0.beta2'
|
7
|
+
spec.authors = ['Lakshya Kapoor']
|
8
|
+
spec.email = ['kapoorlakshya@gmail.com']
|
9
|
+
|
10
|
+
spec.summary = 'Record your computer screen using ffmpeg via Ruby.'
|
11
|
+
spec.description = 'Ruby gem to record your computer screen - desktop or specific application/window' \
|
12
|
+
' - using [FFMPEG](https://www.ffmpeg.org/).'
|
13
|
+
spec.homepage = 'https://github.com/kapoorlakshya/ffmpeg-screenrecorder'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
end
|
19
|
+
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
23
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.6'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
+
spec.add_development_dependency 'watir', '~> 6.0'
|
27
|
+
spec.add_development_dependency 'webdrivers', '~> 3.0'
|
28
|
+
|
29
|
+
spec.add_runtime_dependency 'os', '~> 0.9.0'
|
30
|
+
spec.add_runtime_dependency 'streamio-ffmpeg', '~> 1.0'
|
31
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module FFMPEG
|
2
|
+
class RecorderOptions
|
3
|
+
|
4
|
+
def initialize(options)
|
5
|
+
@options = verify_options options
|
6
|
+
end
|
7
|
+
|
8
|
+
def format
|
9
|
+
@options[:format]
|
10
|
+
end
|
11
|
+
|
12
|
+
def framerate
|
13
|
+
@options[:framerate]
|
14
|
+
end
|
15
|
+
|
16
|
+
def infile
|
17
|
+
@options[:infile]
|
18
|
+
end
|
19
|
+
|
20
|
+
def output
|
21
|
+
@options[:output]
|
22
|
+
end
|
23
|
+
|
24
|
+
def advanced
|
25
|
+
@options[:advanced]
|
26
|
+
end
|
27
|
+
|
28
|
+
def log
|
29
|
+
@options[:log]
|
30
|
+
end
|
31
|
+
|
32
|
+
def log_level
|
33
|
+
@options[:log_level]
|
34
|
+
end
|
35
|
+
|
36
|
+
def all
|
37
|
+
@options
|
38
|
+
end
|
39
|
+
|
40
|
+
def parsed
|
41
|
+
vals = "-f #{@options[:format]} "
|
42
|
+
vals << "-r #{@options[:framerate]} "
|
43
|
+
vals << advanced_options if @options[:advanced]
|
44
|
+
vals << "-i #{determine_infile @options[:infile]} "
|
45
|
+
vals << @options[:output]
|
46
|
+
vals << ffmpeg_log_to(@options[:log]) # If provided
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
#
|
52
|
+
# Verifies the required options are provided
|
53
|
+
#
|
54
|
+
def verify_options(options)
|
55
|
+
missing_options = required_options.select { |req| options[req].nil? }
|
56
|
+
err = "Required options are missing: #{missing_options}"
|
57
|
+
raise(ArgumentError, err) unless missing_options.empty?
|
58
|
+
|
59
|
+
options
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Returns Array of require options a Symbols
|
64
|
+
#
|
65
|
+
def required_options
|
66
|
+
# -f format
|
67
|
+
# -r framerate
|
68
|
+
# -i input
|
69
|
+
# output
|
70
|
+
%i[format framerate infile output]
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Returns advanced options parsed and ready for ffmpeg to receive.
|
75
|
+
#
|
76
|
+
def advanced_options
|
77
|
+
return nil unless @options[:advanced]
|
78
|
+
raise(ArgumentError, ':advanced cannot be empty.') if options[:advanced].empty?
|
79
|
+
|
80
|
+
arr = []
|
81
|
+
options[:advanced].each { |k, v|
|
82
|
+
arr.push "-#{k} #{v}"
|
83
|
+
}
|
84
|
+
arr.join(' ') + ' '
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Determines if the ffmpeg output will be to a log
|
89
|
+
# file based on given options.
|
90
|
+
#
|
91
|
+
def ffmpeg_log_to(file)
|
92
|
+
return " 2> #{file}" if file
|
93
|
+
' > nul 2>&1' # No log file given
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Returns final infile parameter.
|
98
|
+
# Adds title= qualifier to infile parameter
|
99
|
+
# unless the user is recording the desktop.
|
100
|
+
#
|
101
|
+
def determine_infile(opt)
|
102
|
+
return opt if opt == 'desktop'
|
103
|
+
%Q("title=#{opt}")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -1,111 +1,75 @@
|
|
1
|
-
require 'streamio-ffmpeg'
|
2
|
-
require 'os'
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
FFMPEG.logger.debug
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
def
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
FFMPEG.logger.
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
FFMPEG.logger.debug "Logger initialized."
|
77
|
-
end
|
78
|
-
|
79
|
-
def command
|
80
|
-
"#{FFMPEG.ffmpeg_binary} -y " \
|
81
|
-
"#{extra_opts}" \
|
82
|
-
"-f #{opts[:device]} " \
|
83
|
-
"-framerate #{opts[:framerate]} " \
|
84
|
-
"-i #{opts[:input]} " \
|
85
|
-
"#{opts[:output]} " \
|
86
|
-
"2> #{opts[:log]}"
|
87
|
-
end
|
88
|
-
|
89
|
-
def extra_opts
|
90
|
-
return nil unless opts[:extra_opts]
|
91
|
-
raise ':extra_opts cannot be empty.' if opts[:extra_opts].empty?
|
92
|
-
|
93
|
-
arr = []
|
94
|
-
opts[:extra_opts].each { |k, v|
|
95
|
-
arr.push "-#{k} #{v}"
|
96
|
-
}
|
97
|
-
' ' + arr.join(' ') + ' '
|
98
|
-
end
|
99
|
-
|
100
|
-
# def available_inputs_by(application)
|
101
|
-
# `tasklist /v /fi "imagename eq #{application}.exe" /fo list | findstr Window`
|
102
|
-
# .split("\n")
|
103
|
-
# .reject { |title| title == 'Window Title: N/A' }
|
104
|
-
# end
|
105
|
-
#
|
106
|
-
# def input
|
107
|
-
# return opts[:input] if opts[:input] == 'desktop'
|
108
|
-
# %Q(title="#{opts[:input].gsub('Window Title: ', '')}")
|
109
|
-
# end
|
110
|
-
end # class Recorder
|
111
|
-
end # module FFMPEG
|
1
|
+
require 'streamio-ffmpeg'
|
2
|
+
require 'os'
|
3
|
+
require_relative 'recorder_options'
|
4
|
+
require_relative 'windows'
|
5
|
+
|
6
|
+
module FFMPEG
|
7
|
+
class Screenrecorder
|
8
|
+
extend Windows
|
9
|
+
|
10
|
+
attr_reader :options, :video
|
11
|
+
|
12
|
+
def initialize(options = {})
|
13
|
+
@options = RecorderOptions.new(options)
|
14
|
+
@video = nil
|
15
|
+
@process = nil
|
16
|
+
initialize_logger(@options.log_level || Logger::ERROR)
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
@video = nil # New file
|
21
|
+
start_time = Time.now
|
22
|
+
@process = start_ffmpeg
|
23
|
+
elapsed = Time.now - start_time
|
24
|
+
FFMPEG.logger.debug "Process started in #{elapsed}s"
|
25
|
+
FFMPEG.logger.info 'Recording...'
|
26
|
+
end
|
27
|
+
|
28
|
+
def stop
|
29
|
+
FFMPEG.logger.debug 'Stopping ffmpeg.exe...'
|
30
|
+
elapsed = kill_ffmpeg
|
31
|
+
FFMPEG.logger.debug "Stopped ffmpeg.exe in #{elapsed}s"
|
32
|
+
FFMPEG.logger.info 'Recording complete.'
|
33
|
+
@video = Movie.new(options.output)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def start_ffmpeg
|
39
|
+
FFMPEG.logger.debug "Command: #{command}"
|
40
|
+
process = IO.popen(command, 'r+')
|
41
|
+
sleep(1.5) # Takes ~1.5s on average to initialize
|
42
|
+
process
|
43
|
+
end
|
44
|
+
|
45
|
+
def kill_ffmpeg
|
46
|
+
@process.puts 'q' # Gracefully exit ffmpeg
|
47
|
+
elapsed = wait_for_io_eof(5)
|
48
|
+
@process.close_write # Close IO
|
49
|
+
elapsed
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize_logger(level)
|
53
|
+
FFMPEG.logger.progname = 'FFMPEG'
|
54
|
+
FFMPEG.logger.level = level
|
55
|
+
FFMPEG.logger.formatter = proc do |severity, time, progname, msg|
|
56
|
+
"#{time.strftime('%F %T')} #{progname} - #{severity} - #{msg}\n"
|
57
|
+
end
|
58
|
+
FFMPEG.logger.debug 'Logger initialized.'
|
59
|
+
end
|
60
|
+
|
61
|
+
def command
|
62
|
+
cmd = "#{FFMPEG.ffmpeg_binary} -y "
|
63
|
+
cmd << @options.parsed
|
64
|
+
end
|
65
|
+
|
66
|
+
def wait_for_io_eof(timeout)
|
67
|
+
start = Time.now
|
68
|
+
Timeout.timeout(timeout) do
|
69
|
+
sleep(0.1) until @process.eof?
|
70
|
+
end
|
71
|
+
FFMPEG.logger.debug "IO#eof? #{@process.eof?}"
|
72
|
+
Time.now - start
|
73
|
+
end
|
74
|
+
end # class Recorder
|
75
|
+
end # module FFMPEG
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module FFMPEG
|
2
|
+
module Windows
|
3
|
+
|
4
|
+
def window_titles(application)
|
5
|
+
FFMPEG.logger.debug "Retrieving available windows for: #{application}"
|
6
|
+
WindowGrabber.new.available_windows_for application
|
7
|
+
end
|
8
|
+
|
9
|
+
class WindowGrabber
|
10
|
+
def available_windows_for(application)
|
11
|
+
list = `tasklist /v /fi "imagename eq #{application}.exe" /fo list | findstr Window`
|
12
|
+
.split("\n")
|
13
|
+
.reject { |title| title == 'Window Title: N/A' }
|
14
|
+
list.map { |i| i.gsub('Window Title: ', '') } # Make it user friendly
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end # module Windows
|
18
|
+
end # module FFMPEG
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ffmpeg-screenrecorder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lakshya Kapoor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-11-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -122,8 +122,8 @@ dependencies:
|
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '1.0'
|
125
|
-
description:
|
126
|
-
|
125
|
+
description: Ruby gem to record your computer screen - desktop or specific application/window
|
126
|
+
- using [FFMPEG](https://www.ffmpeg.org/).
|
127
127
|
email:
|
128
128
|
- kapoorlakshya@gmail.com
|
129
129
|
executables: []
|
@@ -142,8 +142,10 @@ files:
|
|
142
142
|
- bin/setup
|
143
143
|
- ffmpeg-screenrecorder.gemspec
|
144
144
|
- lib/ffmpeg.rb
|
145
|
+
- lib/ffmpeg/recorder_options.rb
|
145
146
|
- lib/ffmpeg/screenrecorder.rb
|
146
|
-
|
147
|
+
- lib/ffmpeg/windows.rb
|
148
|
+
homepage: https://github.com/kapoorlakshya/ffmpeg-screenrecorder
|
147
149
|
licenses:
|
148
150
|
- MIT
|
149
151
|
metadata: {}
|