ffmpeg-screenrecorder 1.0.0.beta9 → 1.0.0.beta10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12cfdba9f1cb9d3296d231d3cc1c6262ff6f2350a1bd79db2d66db3e12d06e09
4
- data.tar.gz: a8be75c4fe64a40eff487fdc9345f612f185f21c1df7f81f31944a07913af72c
3
+ metadata.gz: 362b8478473163a4c1b072b4bd556560dbad3fd6f50f258e6f6fbebdfb01955c
4
+ data.tar.gz: c9f64e399242f570bf87e0dd1483b92e2bd63c17e8ec97aebe2686067f446f8c
5
5
  SHA512:
6
- metadata.gz: 116ffbcc5f2532a017f5d5fe02d2d44759301ad8955d91e6711fe186941a33064f82fecb03c92f10a12436e6159b0015c8449ddfd2fa439d5aa51b510bc673e2
7
- data.tar.gz: 57867328f8e57dac849f63ba0be69f45fa365a8e6036c38e0c422b3dc3fd43f74b4a07321267cd7452d3ee460ba66d72f35d60764686fbf47240a7d28366fec9
6
+ metadata.gz: 44287d64e556d2ae9ae720c55d9fddeb19acb9085943b083bc88c8eac6c15cebd97ef40f085d01d12a21bddbd4501a2e0eed2036aca5a0f2a8d44f5a52f2ba4c
7
+ data.tar.gz: f94b1e95dd4adb95f3b8f1e0c3f7c374c55009f9afafeef37475aefffb43a0c592c6dd8f27cf152ffad1a9df955a1a78df1730904ac36774352d73de58c59232
@@ -44,4 +44,7 @@ Style/FrozenStringLiteralComment:
44
44
  Enabled: false
45
45
 
46
46
  TrailingBlankLines:
47
+ Enabled: false
48
+
49
+ Layout/MultilineMethodCallIndentation:
47
50
  Enabled: false
data/CHANGES.md CHANGED
@@ -1,3 +1,24 @@
1
+ ### 1.0.0.beta10 (2019-02-05)
2
+ * Fixed an edge case in Microsoft Windows specific implementation of
3
+ `WindowTitles#fetch` where processes with mismatching names and window
4
+ titles, such as process `"Calculator.exe"` with window title `"CicMarshalWnd"`,
5
+ were omitted ([#35](https://github.com/kapoorlakshya/ffmpeg-screenrecorder/issues/35)).
6
+ This fix also prints a warning when this mismatch occurs.
7
+ * The fix for #35 introduces a mild inconvenience when using
8
+ applications like Chrome, which spawn a new process per window or
9
+ extension. `#fetch` now returns titles for these additional processes
10
+ with the visible window (web page) title. In a future release, you will
11
+ be able to use something like `full_match: true` to prevent this.
12
+ * Fixed bug in Linux specific `WindowTitles#fetch` implementation where
13
+ the filter by application name logic was removed. This filter is required
14
+ on Linux here because `wmctrl` returns all open window titles unlike
15
+ Microsoft Windows where `taskmgr` allows us get window titles by process
16
+ name.
17
+ * On Linux, you are now required to provide the `input` as `"desktop"`
18
+ or a display number, such as `":0.0"`. Run `echo $DISPLAY` to check your display number.
19
+ * QOL improvements - Type checking of inputs, spec cleanup, added more
20
+ tests, and fixed rubocop warnings.
21
+
1
22
  ### 1.0.0.beta9 (2019-01-22)
2
23
 
3
24
  * :warning: `FFMPEG::RecordingRegions` is now `FFMPEG::WindowTitles`, so the module name is true to the function it provides.
data/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![Gem Version](https://badge.fury.io/rb/ffmpeg-screenrecorder.svg)](https://badge.fury.io/rb/ffmpeg-screenrecorder)
4
4
  ![https://rubygems.org/gems/ffmpeg-screenrecorder](https://ruby-gem-downloads-badge.herokuapp.com/ffmpeg-screenrecorder?type=total)
5
5
  [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/kapoorlakshya/ffmpeg-screenrecorder/master)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/a176dc755e06a23e5db8/maintainability)](https://codeclimate.com/github/kapoorlakshya/ffmpeg-screenrecorder/maintainability)
6
7
 
7
8
  Ruby gem to record your computer screen - desktop or specific application/window - using [FFmpeg](https://www.ffmpeg.org/).
8
9
 
@@ -12,33 +13,18 @@ Supports Windows and Linux as of version `1.0.0-beta5`. macOS support will be ad
12
13
 
13
14
  ## Installation
14
15
 
15
- On Microsoft Windows, [download](https://www.ffmpeg.org/download.html#build-windows), extract and add the location of `/bin` to your ENV `PATH` variable. If you want to use `libx264`, download
16
- [this build](https://ffmpeg.zeranoe.com/builds/) instead.
17
-
18
- For Linux, follow instructions here - https://ffmpeg.org/download.html#build-linux
19
-
20
- Once installed, make sure ffmpeg is found:
21
-
22
- $ ffmpeg -version
23
- ffmpeg version N-92132-g0a41a8bf29 Copyright (c) 2000-2018 the FFmpeg developers
24
- built with gcc 8.2.1 (GCC) 20180813
25
- configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-g
26
- nutls --enable-iconv --enable-libass --enable-libbluray --enable-libfreetype --enable-libm
27
- p3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable
28
- -libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable
29
- -libtwolame --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable
30
- -libx265 --enable-libxml2 --enable-libzimg --enable-lzma --enable-zlib --enable-gmp --enab
31
- le-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libsp
32
- eex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --ena
33
- ble-cuvid --enable-d3d11va --enable-nvenc --enable-nvdec --enable-dxva2 --enable-avisynth
34
- libavutil 56. 19.101 / 56. 19.101
35
- libavcodec 58. 32.100 / 58. 32.100
36
- libavformat 58. 18.104 / 58. 18.104
37
- libavdevice 58. 4.105 / 58. 4.105
38
- libavfilter 7. 33.100 / 7. 33.100
39
- libswscale 5. 2.100 / 5. 2.100
40
- libswresample 3. 2.100 / 3. 2.100
41
- libpostproc 55. 2.100 / 55. 2.100
16
+ #### 1. Setup FFmpeg
17
+
18
+ | OS | Download |
19
+ |-------------------|--------------------------------------------------------------------------------|
20
+ | Microsoft Windows | [ffmpeg.org#build-windows](https://www.ffmpeg.org/download.html#build-windows) or [libx264 enabled build](https://ffmpeg.zeranoe.com/builds/) |
21
+ | Linux | [ffmpeg.org#build-linux](https://ffmpeg.org/download.html#build-linux) |
22
+ | macOS | [ffmpeg.org#build-mac](https://www.ffmpeg.org/download.html#build-mac) |
23
+
24
+ Add location of the `ffmpeg/bin` folder to `PATH` environment variable if using Microsoft Windows ([instructions](https://windowsloop.com/install-ffmpeg-windows-10/)).
25
+ Alternatively, you can define the location using `FFMPEG.ffmpeg_binary='/path/to/binary'` in your project.
26
+
27
+ #### 2. Install gem
42
28
 
43
29
  Next, add this line to your application's Gemfile:
44
30
 
@@ -48,65 +34,57 @@ gem 'ffmpeg-screenrecorder'
48
34
 
49
35
  And then execute:
50
36
 
51
- $ bundle
37
+ ```bash
38
+ $ bundle
39
+ ```
52
40
 
53
41
  Or install it yourself as:
54
42
 
55
- $ gem install ffmpeg-screenrecorder
56
-
57
- Require it in your project and start using the gem:
58
-
59
- require ffmpeg-screenrecorder
60
-
61
- ## Usage
62
-
63
- #### Required Options
64
-
65
- - `:input` - `'desktop'` or application window name
66
- - `:output` - Output file location/name
67
- - `:framerate` - Capture FPS
68
-
69
- #### Advanced Options
43
+ ```bash
44
+ $ gem install ffmpeg-screenrecorder --pre
45
+ ```
70
46
 
71
- - `:log` - Defaults to `ffmpeg.log`
72
- - `:log_level` for this gem
47
+ #### 3. Require gem
73
48
 
74
- All other FFmpeg options can be passed through the `advanced` key. This feature is yet to be fully tested, so please feel free to report any bugs or request a feature.
49
+ Require this gem in your project and start using the gem:
75
50
 
76
- ```
77
- opts = { input: 'desktop',
78
- output: 'recorder-test.mp4',
79
- framerate: 15,
80
- log: 'recorder.log',
81
- log_level: Logger::DEBUG, # For gem
82
- advanced: { loglevel: 'level+debug', # For FFmpeg
83
- video_size: '640x480',
84
- show_region: '1' }
85
- }
51
+ ```ruby
52
+ require 'ffmpeg-screenrecorder'
86
53
  ```
87
54
 
88
55
  ##### Record Desktop
89
56
 
90
- ```
57
+ ```ruby
91
58
  opts = { input: 'desktop',
92
- output: 'screenrecorder-desktop.mp4',
59
+ output: 'recording.mp4',
93
60
  framerate: 15.0 }
94
61
  @recorder = FFMPEG::ScreenRecorder.new(opts)
95
-
96
- # Start recording
97
- @recorder.start #=> #<IO:fd 5>
62
+ @recorder.start
98
63
 
99
64
  # ... Run tests or whatever you want to record
100
65
 
101
- # Stop recording
102
- @recorder.stop #=> #<FFMPEG::Movie...>
66
+ @recorder.stop
103
67
 
104
- # Recorded file
105
- @recorder.video #=> #<FFMPEG::Movie...>
68
+ # Recorded file metadata
69
+ @recorder.video
70
+ #=> #<FFMPEG::Movie:0x00000000067e0a08
71
+ @path="screenrecorder-desktop.mp4",
72
+ @container="mov,mp4,m4a,3gp,3g2,mj2",
73
+ @duration=5.0,
74
+ @time=0.0,
75
+ @creation_time=nil,
76
+ @bitrate=1051,
77
+ @rotation=nil,
78
+ @video_stream="h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 2560x1440, 1048 kb/s, 15 fps, 15 tbr, 15360 tbn, 30 tbc (default)",
79
+ @audio_stream=nil,
80
+ @video_codec="h264 (High 4:4:4 Predictive) (avc1 / 0x31637661)", @colorspace="yuv444p",
81
+ @video_bitrate=1048,
82
+ @resolution="2560x1440">
106
83
  ```
107
84
 
108
- ##### Record Application Window - Microsoft Windows (`gdigrab`) Only
109
- ```
85
+ ##### Record Application Window
86
+
87
+ ```ruby
110
88
  require 'watir'
111
89
 
112
90
  browser = Watir::Browser.new :firefox
@@ -115,33 +93,62 @@ FFMPEG::WindowTitles.fetch('firefox') # Name of exe
115
93
  #=> ["Mozilla Firefox"]
116
94
 
117
95
  opts = { input: FFMPEG::WindowTitles.fetch('firefox').first,
118
- output: 'screenrecorder-firefox.mp4',
119
- framerate: 15.0,
120
- log: 'screenrecorder-firefox.log' }
96
+ output: 'recording.mp4',
97
+ framerate: 15.0 }
121
98
  @recorder = FFMPEG::ScreenRecorder.new(opts)
122
-
123
- # Start recording
124
99
  @recorder.start
125
100
 
126
101
  # Run tests or whatever you want to record
127
- browser.goto 'watir.com'
128
- browser.link(text: 'News').wait_until_present.click
129
102
 
130
- # Stop recording
131
103
  @recorder.stop
132
-
133
104
  browser.quit
134
105
  ```
135
106
 
136
- <b>Note</b>:
137
- - Always stop the recording before closing the application. Otherwise, ffmpeg will force exit as soon as the window disappears and may produce an invalid video file.
138
- - If you're launching multiple applications or testing an application at different window sizes, recording the `desktop` is a better option.
107
+ <b>Limitations</b>:
108
+ - Only works on Microsoft Windows (gdigrab).
109
+ - `#fetch` only returns titles from currently active (visible) windows.
110
+ - `#fetch` may return `ArgumentError (invalid byte sequence in UTF-8)`
111
+ for a window title with non `UTF-8` characters.
112
+ See [#38](https://github.com/kapoorlakshya/ffmpeg-screenrecorder/issues/38)
113
+ for workaround.
114
+ - Always stop the recording before closing the application. Otherwise,
115
+ ffmpeg will force exit as soon as the window disappears and may produce
116
+ an invalid video file.
117
+ - If you're launching multiple applications or testing an application
118
+ at different window sizes, recording the `desktop` is a better option.
119
+
120
+ #### Options
139
121
 
140
- ## Demo
122
+ - `:input` - `'desktop'` or application window name
123
+ - `:output` - Output file location/name
124
+ - `:framerate` - Capture FPS
125
+ - `:log` - Defaults to `ffmpeg.log`
126
+ - `:log_level` for this gem. Default: ERROR
127
+
128
+ All other FFmpeg options can be passed through the `advanced` key. This feature is yet to be fully tested, so please feel free to report any bugs or request a feature.
129
+
130
+ ```ruby
131
+ opts = { input: 'desktop',
132
+ output: 'recorder-test.mp4',
133
+ framerate: 15,
134
+ log: 'recorder.log',
135
+ log_level: Logger::DEBUG, # For gem
136
+ advanced: { loglevel: 'level+debug', # For FFmpeg
137
+ video_size: '640x480',
138
+ show_region: '1' }
139
+ }
141
140
 
142
- You can find example video recordings here - [https://kapoorlakshya.github.io/introducing-ffmpeg-screenrecorder](https://kapoorlakshya.github.io/introducing-ffmpeg-screenrecorder)
141
+ #
142
+ # Command to FFmpeg:
143
+ #
144
+ # ffmpeg -y -f gdigrab -r 15 -loglevel level+debug -video_size 640x480
145
+ # -show_region 1 -i desktop recorder-test.mp4 2> recorder.log
146
+ ```
143
147
 
144
- Cucumber + Watir based example - [kapoorlakshya/cucumber-watir-test-recorder-example](https://github.com/kapoorlakshya/cucumber-watir-test-recorder-example)
148
+ ## Demo
149
+
150
+ You can find example video recordings [here](https://kapoorlakshya.github.io/introducing-ffmpeg-screenrecorder).
151
+ Cucumber + Watir based example is [here](https://github.com/kapoorlakshya/cucumber-watir-test-recorder-example).
145
152
 
146
153
  ## Development
147
154
 
@@ -162,6 +169,12 @@ The gem is available as open source under the terms of the [MIT License](https:/
162
169
 
163
170
  ## Credits
164
171
 
172
+ [![Streamio](http://d253c4ja9jigvu.cloudfront.net/assets/small-logo.png)](http://streamio.com)
173
+
174
+ This gem is based on the [streamio-ffmpeg](https://github.com/streamio/streamio-ffmpeg) gem.
175
+ <br />
176
+ <br />
177
+
165
178
  ![SauceLabs Logo](https://saucelabs.com/content/images/logo.png)
166
179
 
167
180
  Thanks to [SauceLabs](https://saucelabs.com) for providing me with a free account. If you manage an open source project, you can apply for a free account [here](https://saucelabs.com/open-source).
@@ -4,12 +4,8 @@ module FFMPEG
4
4
  DEFAULT_LOG_FILE = 'ffmpeg.log'.freeze
5
5
 
6
6
  def initialize(options)
7
- raise ArgumentError, "Expected Hash, given: #{options.class}" unless options.is_a? Hash
8
-
9
- if options[:advanced]
10
- raise ArgumentError, "Expected Hash, given: #{options.class}" unless options[:advanced].is_a? Hash
11
- end
12
-
7
+ TypeChecker.check options, Hash
8
+ TypeChecker.check options[:advanced], Hash if options[:advanced]
13
9
  @options = verify_options options
14
10
  end
15
11
 
@@ -86,7 +82,8 @@ module FFMPEG
86
82
 
87
83
  #
88
84
  # Verifies the required options are provided and returns
89
- # the given options Hash
85
+ # the given options Hash. Raises ArgumentError if all required
86
+ # options are not present in the given Hash.
90
87
  #
91
88
  def verify_options(options)
92
89
  missing_options = required_options.select { |req| options[req].nil? }
@@ -100,12 +97,7 @@ module FFMPEG
100
97
  # Returns Array of required options sa Symbols
101
98
  #
102
99
  def required_options
103
- # -r framerate
104
- # -i input
105
- # output
106
- return %i[framerate input output] unless OS.linux?
107
-
108
- %i[framerate output] # Linux
100
+ %i[framerate input output]
109
101
  end
110
102
 
111
103
  #
@@ -138,7 +130,11 @@ module FFMPEG
138
130
  #
139
131
  def determine_input
140
132
  # x11grab doesn't support window capture
141
- return ':99' if OS.linux?
133
+ if OS.linux?
134
+ return ':0.0' if @options[:input] == 'desktop'
135
+
136
+ return @options[:input] # User given display number
137
+ end
142
138
 
143
139
  return @options[:input] if @options[:input] == 'desktop'
144
140
 
@@ -1,4 +1,5 @@
1
1
  require 'fileutils'
2
+ require_relative 'type_checker'
2
3
  require_relative 'recorder_errors'
3
4
  require_relative 'recorder_options'
4
5
  require_relative 'window_titles'
@@ -0,0 +1,12 @@
1
+ module FFMPEG
2
+ # @since 1.0.0.beta10
3
+ module TypeChecker
4
+ #
5
+ # Compares the given object's type (class) to the desired object type.
6
+ # Raises an ArgumentError if the object is not of desired type.
7
+ #
8
+ def self.check(obj, klass)
9
+ raise ArgumentError, "Expected #{klass}, given: #{obj.class}" unless obj.is_a? klass
10
+ end
11
+ end
12
+ end
@@ -1,5 +1,5 @@
1
1
  module FFMPEG
2
2
  class ScreenRecorder
3
- VERSION = '1.0.0.beta9'.freeze
3
+ VERSION = '1.0.0.beta10'.freeze
4
4
  end
5
5
  end
@@ -1,6 +1,8 @@
1
1
  module FFMPEG
2
2
  # @since 1.0.0-beta4
3
3
  module WindowTitles
4
+ IGNORED_WINDOW_TITLES = %r{^Window Title:( N/A|\s+)?} # From Chrome extensions
5
+
4
6
  #
5
7
  # Returns a list of available window titles for the given application (process) name.
6
8
  #
@@ -25,32 +27,33 @@ module FFMPEG
25
27
  private
26
28
 
27
29
  #
28
- # Returns list of windows when using Microsoft Windows
30
+ # Returns list of window titles in FFmpeg expected format when using Microsoft Windows
29
31
  #
30
32
  def windows_os_window(application)
31
- raw_list = `tasklist /v /fi "imagename eq #{application}.exe" /fo list | findstr Window`
32
- .split("\n")
33
- .select { |t| t.match?(/#{application}/i) } # Narrow down to given application
34
- final_list = raw_list.map { |i| i.gsub('Window Title: ', '') } # Match ffmpeg expected format
35
- raise RecorderErrors::ApplicationNotFound, "No open windows found for: #{application}.exe" if final_list.empty?
33
+ titles = `tasklist /v /fi "imagename eq #{application}.exe" /fo list | findstr Window`
34
+ .split("\n")
35
+ .map { |i| i.gsub(IGNORED_WINDOW_TITLES, '') }
36
+ .reject(&:empty?)
37
+ raise RecorderErrors::ApplicationNotFound, "No open windows found for: #{application}.exe" if titles.empty?
36
38
 
37
- final_list
39
+ warn_on_mismatch(titles, application)
40
+ titles
38
41
  end
39
42
 
40
43
  #
41
- # Returns list of windows when using Linux
44
+ # Returns list of window titles in FFmpeg expected format when using Linux
42
45
  #
43
46
  def linux_os_window(application)
44
- FFMPEG.logger.warn 'Note: Default capture device x11grab on Linux does not support window recording.'
45
- raise DependencyNotFound, 'wmctrl is not installed. Run: sudo apt-get install wmctrl.' unless wmctrl_installed?
47
+ FFMPEG.logger.warn 'Default capture device on Linux (x11grab) does not support window recording.'
48
+ raise DependencyNotFound, 'wmctrl is not installed. Run: sudo apt install wmctrl.' unless wmctrl_installed?
46
49
 
47
- final_list = `wmctrl -l | awk '{$3=""; $2=""; $1=""; print $0}'` # Returns all open windows
48
- .split("\n")
49
- .map(&:strip)
50
- .select { |t| t.match?(/#{application}/i) } # Narrow down to given application
51
- raise RecorderErrors::ApplicationNotFound, "No open windows found for: #{application}" if final_list.empty?
50
+ titles = `wmctrl -l | awk '{$3=""; $2=""; $1=""; print $0}'` # Returns all open windows
51
+ .split("\n")
52
+ .map(&:strip)
53
+ .select { |t| t.match?(/#{application}/i) } # Narrow down to given application
54
+ raise RecorderErrors::ApplicationNotFound, "No open windows found for: #{application}" if titles.empty?
52
55
 
53
- final_list
56
+ titles
54
57
  end
55
58
 
56
59
  #
@@ -59,6 +62,17 @@ module FFMPEG
59
62
  def wmctrl_installed?
60
63
  !`which wmctrl`.empty? # "" when not found
61
64
  end
62
- end
65
+
66
+ #
67
+ # Prints a warning if the retrieved list of window titles does no include
68
+ # the given application process name, which applications commonly do.
69
+ #
70
+ def warn_on_mismatch(titles, application)
71
+ unless titles.map(&:downcase).join(',').include? application.to_s
72
+ FFMPEG.logger.warn "Process name and window title(s) do not match: #{titles}"
73
+ FFMPEG.logger.warn "Please manually provide the displayed window title."
74
+ end
75
+ end
76
+ end # class WindowGrabber
63
77
  end # module Windows
64
78
  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.beta9
4
+ version: 1.0.0.beta10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lakshya Kapoor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-23 00:00:00.000000000 Z
11
+ date: 2019-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry-byebug
@@ -132,6 +132,7 @@ files:
132
132
  - lib/ffmpeg/recorder_errors.rb
133
133
  - lib/ffmpeg/recorder_options.rb
134
134
  - lib/ffmpeg/screenrecorder.rb
135
+ - lib/ffmpeg/type_checker.rb
135
136
  - lib/ffmpeg/version.rb
136
137
  - lib/ffmpeg/window_titles.rb
137
138
  homepage: http://github.com/kapoorlakshya/ffmpeg-screenrecorder