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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a02c5c9cc4db8684c4a6f3f2f557b0857089c488ef26fc0f6986d7db32ff95cf
4
- data.tar.gz: 03c1e725b98ed53f12d954ad084cf86ebfe41514319ebe14e58aec091029809a
3
+ metadata.gz: e85788e1924b1350003ba607d5cec470878cb2ecc49a5cf53d5508c4604cb38d
4
+ data.tar.gz: b438f32841d00eb3c6d3b6a996379f61a9c5e1c4a74335729bd6fc725bf23bae
5
5
  SHA512:
6
- metadata.gz: 9c3582ca908bb205de16bf887db6750574b5ade7ad3d83e57bb4aada8a092715a121a8681dbcbf3676cce70ec711545a2472d6e46234e6015232b6c0f1af5237
7
- data.tar.gz: 2226a59c6416d4d54a60313e849f09fdff30f6efda276678256b3799b56667d91f126793794c6bf44b72c32005eb8122e058cee88056f42edae033d0ae537f5c
6
+ metadata.gz: f36dafd064d1363b8dd5c42e39c2b840bc6a68db1cc7d42b8c65a667b78e45140c304a47581350a32913a79e6860f34d82778cb89510ec4c1f5925b35f22ee8f
7
+ data.tar.gz: 98763086b2b600ee80cc319b0b5a86bd598aa5e561f309c929afc613ae002caccf535ebb0d00050ad1a75380fd2d87f3e44b106dd13304571b2d13b5499f6a88
data/.gitignore CHANGED
@@ -14,6 +14,7 @@ Gemfile.lock # Part of best practice
14
14
  /pkg/
15
15
  /spec/reports/
16
16
  /tmp/
17
+ /webdrivers_bin
17
18
 
18
19
  Gemfile.lock
19
20
 
@@ -1,5 +1,5 @@
1
1
  Style/EndOfLine:
2
- EnforcedStyle: lf
2
+ EnforcedStyle: crlf
3
3
 
4
4
  Metrics/LineLength:
5
5
  Max: 120
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
- TODO: Write usage instructions here
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.beta'
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 = 'A ruby gem based on streamio-ffmpeg gem to record your computer screen in various formats.'
12
- spec.homepage = 'https://github.com/kapoorlakshya/ruby-ffmpeg_screenrecorder'
13
- spec.license = 'MIT'
14
-
15
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
16
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
- end
18
-
19
- spec.require_paths = ['lib']
20
-
21
- spec.add_development_dependency 'bundler', '~> 1.16'
22
- spec.add_development_dependency 'pry-byebug', '~> 3.6'
23
- spec.add_development_dependency 'rake', '~> 10.0'
24
- spec.add_development_dependency 'rspec', '~> 3.0'
25
- spec.add_development_dependency 'watir', '~> 6.0'
26
- spec.add_development_dependency 'webdrivers', '~> 3.0'
27
-
28
- spec.add_runtime_dependency 'os', '~> 0.9.0'
29
- spec.add_runtime_dependency 'streamio-ffmpeg', '~> 1.0'
30
- end
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
- module FFMPEG
5
- class Screenrecorder
6
- attr_reader :opts, :output, :process_id
7
-
8
- def initialize(opts = {})
9
- @opts = default_config.merge opts
10
- @output = opts[:output]
11
- @video_file = nil
12
- @process_id = nil
13
- init_logger(opts[:logging_level])
14
- end
15
-
16
- def opts=(new_opts)
17
- @opts = default_config.merge new_opts
18
- @output = opts[:output]
19
- init_logger(opts[:logging_level]) if FFMPEG.logger.level != opts[:logging_level]
20
- end
21
-
22
- def start
23
- FFMPEG.logger.debug "Starting: #{command}"
24
- @video_file = nil # New file
25
- @process_id = start_ffmpeg
26
- FFMPEG.logger.info 'Recording...'
27
- @process_id
28
- end
29
-
30
- def stop
31
- FFMPEG.logger.debug 'Stopping ffmpeg.exe...'
32
- # msg = Process.kill('INT', @process_id)
33
- # Process.detach(@process_id)
34
- msg = kill_ffmpeg
35
- FFMPEG.logger.debug msg
36
- FFMPEG.logger.debug 'Stopped ffmpeg.exe'
37
- FFMPEG.logger.info 'Recording complete.'
38
- msg
39
- end
40
-
41
- # def inputs(application)
42
- # FFMPEG.logger.debug "Retrieving available windows from: #{application}"
43
- # available_inputs_by application
44
- # end
45
-
46
- def video_file
47
- @video_file ||= Movie.new(output)
48
- end
49
-
50
- private
51
-
52
- def default_config
53
- { input: 'desktop',
54
- framerate: 15,
55
- device: 'gdigrab',
56
- log: 'ffmpeg_recorder_log.txt' }
57
- end
58
-
59
- def start_ffmpeg
60
- spawn(command)
61
- pid = `powershell (Get-Process ffmpeg).id`.to_i
62
- raise 'ffmpeg failed to start.' if pid.zero?
63
- pid
64
- end
65
-
66
- def kill_ffmpeg
67
- `TASKKILL /f /im ffmpeg.exe`
68
- end
69
-
70
- def init_logger(level)
71
- FFMPEG.logger.progname = 'FFMPEG::Recorder'
72
- FFMPEG.logger.level = level
73
- FFMPEG.logger.formatter = proc do |severity, time, progname, msg|
74
- "#{time.strftime('%F %T')} #{progname} - #{severity} - #{msg}\n"
75
- end
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.beta
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-10-27 00:00:00.000000000 Z
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: A ruby gem based on streamio-ffmpeg gem to record your computer screen
126
- in various formats.
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
- homepage: https://github.com/kapoorlakshya/ruby-ffmpeg_screenrecorder
147
+ - lib/ffmpeg/windows.rb
148
+ homepage: https://github.com/kapoorlakshya/ffmpeg-screenrecorder
147
149
  licenses:
148
150
  - MIT
149
151
  metadata: {}