ffmpeg-screenrecorder 1.0.0.beta9 → 1.0.0.beta10

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: 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