ffmpeg_core 0.2.0 → 0.4.0
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/CHANGELOG.md +20 -0
- data/README.md +92 -18
- data/lefthook.yml +8 -0
- data/lib/ffmpeg_core/configuration.rb +26 -0
- data/lib/ffmpeg_core/movie.rb +3 -0
- data/lib/ffmpeg_core/probe.rb +24 -2
- data/lib/ffmpeg_core/transcoder.rb +75 -2
- data/lib/ffmpeg_core/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: afead7a6fce7f95748207153b521b35a223f2efd7add35664e12ba3e27f86b23
|
|
4
|
+
data.tar.gz: 3052072fb4a3541518cc5d12bf333b58b77a77f2b3b4deec44d51b89ddbac678
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d725d25a1d211186ede000ac81d58f20c57fc8f46ba5a3897b006a8e92e128b37f5f9cfb9295633bfe0a7dd878a0f99793329c388c1c2a920bc585256b4740db
|
|
7
|
+
data.tar.gz: 5e683ec8fb39dc1e669abaeaa8e3f7254de8f92ef4593ed6869ba7a5a4c02dab2d6ee8005243dbf31e24be27b11a689c89de736c0eca69e93be38b7d9e5fc531
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-01-26
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Complex Filters & Mapping:** Added `filter_graph` (for `-filter_complex`) and `maps` (for `-map`) options to `transcode`.
|
|
13
|
+
- **Hardware Acceleration:** Added `:hwaccel` option to `transcode` (supports `:nvenc`, `:vaapi`, `:qsv`) with automatic encoder detection.
|
|
14
|
+
|
|
15
|
+
## [0.3.0] - 2026-01-16
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Remote Input Support:** `Movie.new` now accepts HTTP, HTTPS, RTMP, and RTSP URLs.
|
|
20
|
+
- **Crop Support:** Added `crop` option to `transcode` (e.g., `crop: { width: 100, height: 100, x: 10, y: 10 }`).
|
|
21
|
+
- **Advanced Metadata:** Added `video_profile` and `video_level` to `Probe`.
|
|
22
|
+
- Rotation detection from `side_data_list` for better compatibility with newer video formats.
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Rotation Geometry:** `Probe#width` and `Probe#height` now correctly swap values if the video is rotated 90 or 270 degrees.
|
|
27
|
+
|
|
8
28
|
## [0.2.0] - 2026-01-15
|
|
9
29
|
|
|
10
30
|
### Added
|
data/README.md
CHANGED
|
@@ -11,6 +11,8 @@ Modern Ruby wrapper for FFmpeg with clean API and proper error handling.
|
|
|
11
11
|
- Zero runtime dependencies
|
|
12
12
|
- **Real-time progress reporting**
|
|
13
13
|
- **Support for video/audio filters and quality presets**
|
|
14
|
+
- **Hardware Acceleration (NVENC, VAAPI, QSV)**
|
|
15
|
+
- **Remote input support (HTTP/HTTPS/RTMP/RTSP)**
|
|
14
16
|
- Proper error handling with detailed context
|
|
15
17
|
- Thread-safe configuration
|
|
16
18
|
- Simple, intuitive API
|
|
@@ -41,19 +43,26 @@ bundle install
|
|
|
41
43
|
```ruby
|
|
42
44
|
require "ffmpeg_core"
|
|
43
45
|
|
|
44
|
-
# Load a video file
|
|
46
|
+
# Load a video file or remote URL
|
|
45
47
|
movie = FFmpegCore::Movie.new("input.mp4")
|
|
48
|
+
# movie = FFmpegCore::Movie.new("http://example.com/video.mp4")
|
|
46
49
|
|
|
47
50
|
# Get metadata
|
|
48
51
|
movie.duration # => 120.5 (seconds)
|
|
49
|
-
movie.resolution # => "1920x1080"
|
|
52
|
+
movie.resolution # => "1920x1080" (automatically swapped if rotated)
|
|
53
|
+
movie.width # => 1920
|
|
54
|
+
movie.height # => 1080
|
|
50
55
|
movie.video_codec # => "h264"
|
|
51
56
|
movie.audio_codec # => "aac"
|
|
52
57
|
movie.frame_rate # => 29.97
|
|
53
58
|
movie.bitrate # => 5000 (kb/s)
|
|
54
|
-
movie.rotation # => 90 (degrees)
|
|
55
|
-
movie.aspect_ratio # => "16:9"
|
|
56
59
|
movie.valid? # => true
|
|
60
|
+
|
|
61
|
+
# Access detailed metadata via probe
|
|
62
|
+
movie.probe.rotation # => 90 (degrees)
|
|
63
|
+
movie.probe.aspect_ratio # => "16:9"
|
|
64
|
+
movie.probe.video_profile # => "High"
|
|
65
|
+
movie.probe.video_level # => 41
|
|
57
66
|
```
|
|
58
67
|
|
|
59
68
|
### Transcoding
|
|
@@ -71,13 +80,76 @@ movie.transcode("output.mp4", {
|
|
|
71
80
|
video_codec: "libx264",
|
|
72
81
|
audio_codec: "aac",
|
|
73
82
|
video_bitrate: "1000k",
|
|
83
|
+
audio_bitrate: "128k",
|
|
74
84
|
resolution: "1280x720",
|
|
85
|
+
crop: { width: 500, height: 500, x: 10, y: 10 }, # Crop video
|
|
75
86
|
video_filter: "scale=1280:-1,transpose=1", # Resize and rotate
|
|
87
|
+
audio_filter: "volume=0.5", # Reduce volume
|
|
76
88
|
preset: "slow", # ffmpeg preset (ultrafast, fast, medium, slow, etc.)
|
|
77
89
|
crf: 23 # Constant Rate Factor (0-51)
|
|
78
90
|
})
|
|
79
91
|
```
|
|
80
92
|
|
|
93
|
+
### Complex Filter Graphs & Stream Mapping
|
|
94
|
+
|
|
95
|
+
Use structured APIs for `-filter_complex` and `-map` to build complex pipelines without raw string hacks.
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
movie.transcode("out.mp4", {
|
|
99
|
+
filter_graph: [
|
|
100
|
+
"[0:v]crop=320:240:0:0[c]",
|
|
101
|
+
"[c]scale=640:480[outv]"
|
|
102
|
+
],
|
|
103
|
+
maps: ["[outv]", "0:a"]
|
|
104
|
+
})
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Hardware Acceleration
|
|
108
|
+
|
|
109
|
+
Opt-in to hardware-accelerated encoding with automatic encoder detection and graceful fallback.
|
|
110
|
+
|
|
111
|
+
```ruby
|
|
112
|
+
# Automatically switches to h264_nvenc if available, falls back to libx264 otherwise
|
|
113
|
+
movie.transcode("out.mp4", hwaccel: :nvenc)
|
|
114
|
+
|
|
115
|
+
# Supports :nvenc, :vaapi, and :qsv
|
|
116
|
+
movie.transcode("out.mp4", hwaccel: :vaapi)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Using Filters
|
|
120
|
+
|
|
121
|
+
FFmpegCore supports raw FFmpeg filter strings for both video (`video_filter` or `-vf`) and audio (`audio_filter` or `-af`).
|
|
122
|
+
|
|
123
|
+
**Common Video Filters:**
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
movie.transcode("output.mp4", {
|
|
127
|
+
# Scale to width 1280, keep aspect ratio
|
|
128
|
+
video_filter: "scale=1280:-1",
|
|
129
|
+
|
|
130
|
+
# Crop 100x100 starting at position (10,10)
|
|
131
|
+
video_filter: "crop=100:100:10:10",
|
|
132
|
+
|
|
133
|
+
# Rotate 90 degrees clockwise
|
|
134
|
+
video_filter: "transpose=1",
|
|
135
|
+
|
|
136
|
+
# Chain multiple filters (Scale then Rotate)
|
|
137
|
+
video_filter: "scale=1280:-1,transpose=1"
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Common Audio Filters:**
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
movie.transcode("output.mp4", {
|
|
145
|
+
# Increase volume by 50%
|
|
146
|
+
audio_filter: "volume=1.5",
|
|
147
|
+
|
|
148
|
+
# Fade in first 5 seconds
|
|
149
|
+
audio_filter: "afade=t=in:ss=0:d=5"
|
|
150
|
+
})
|
|
151
|
+
```
|
|
152
|
+
|
|
81
153
|
### Screenshots
|
|
82
154
|
|
|
83
155
|
```ruby
|
|
@@ -86,7 +158,7 @@ movie = FFmpegCore::Movie.new("input.mp4")
|
|
|
86
158
|
# Extract screenshot at specific time
|
|
87
159
|
movie.screenshot("thumbnail.jpg", seek_time: 5)
|
|
88
160
|
|
|
89
|
-
# With resolution
|
|
161
|
+
# With resolution and quality
|
|
90
162
|
movie.screenshot("thumbnail.jpg", {
|
|
91
163
|
seek_time: 10,
|
|
92
164
|
resolution: "640x360",
|
|
@@ -106,7 +178,7 @@ end
|
|
|
106
178
|
|
|
107
179
|
## Error Handling
|
|
108
180
|
|
|
109
|
-
FFmpegCore provides specific error classes for different failure scenarios
|
|
181
|
+
FFmpegCore provides specific error classes for different failure scenarios. All execution errors (transcoding, probing, screenshots) inherit from `FFmpegCore::ExecutionError`, which provides access to the command, exit status, and stderr output.
|
|
110
182
|
|
|
111
183
|
```ruby
|
|
112
184
|
begin
|
|
@@ -115,9 +187,9 @@ begin
|
|
|
115
187
|
rescue FFmpegCore::InvalidInputError => e
|
|
116
188
|
# File doesn't exist or is not readable
|
|
117
189
|
puts "Input error: #{e.message}"
|
|
118
|
-
rescue FFmpegCore::
|
|
119
|
-
#
|
|
120
|
-
puts "
|
|
190
|
+
rescue FFmpegCore::ExecutionError => e
|
|
191
|
+
# Covers TranscodingError, ProbeError, and ScreenshotError
|
|
192
|
+
puts "Execution failed: #{e.message}"
|
|
121
193
|
puts "Command: #{e.command}"
|
|
122
194
|
puts "Exit status: #{e.exit_status}"
|
|
123
195
|
puts "Stderr: #{e.stderr}"
|
|
@@ -129,14 +201,16 @@ end
|
|
|
129
201
|
|
|
130
202
|
### Error Classes
|
|
131
203
|
|
|
132
|
-
| Error | Description |
|
|
133
|
-
| --------------------------------- | -------------------------------------- |
|
|
134
|
-
| `FFmpegCore::Error` | Base error class |
|
|
135
|
-
| `FFmpegCore::BinaryNotFoundError` | FFmpeg/FFprobe not found |
|
|
136
|
-
| `FFmpegCore::InvalidInputError` | Input file doesn't exist or unreadable |
|
|
137
|
-
| `FFmpegCore::
|
|
138
|
-
| `FFmpegCore::
|
|
139
|
-
| `FFmpegCore::
|
|
204
|
+
| Error | Description | Parent |
|
|
205
|
+
| --------------------------------- | -------------------------------------- | ------ |
|
|
206
|
+
| `FFmpegCore::Error` | Base error class | StandardError |
|
|
207
|
+
| `FFmpegCore::BinaryNotFoundError` | FFmpeg/FFprobe not found | Error |
|
|
208
|
+
| `FFmpegCore::InvalidInputError` | Input file doesn't exist or unreadable | Error |
|
|
209
|
+
| `FFmpegCore::OutputError` | Output file cannot be written | Error |
|
|
210
|
+
| `FFmpegCore::ExecutionError` | Base for command execution errors | Error |
|
|
211
|
+
| `FFmpegCore::ProbeError` | Failed to extract metadata | ExecutionError |
|
|
212
|
+
| `FFmpegCore::TranscodingError` | FFmpeg transcoding failed | ExecutionError |
|
|
213
|
+
| `FFmpegCore::ScreenshotError` | Screenshot extraction failed | ExecutionError |
|
|
140
214
|
|
|
141
215
|
## Development
|
|
142
216
|
|
|
@@ -153,4 +227,4 @@ bundle exec rubocop
|
|
|
153
227
|
|
|
154
228
|
## License
|
|
155
229
|
|
|
156
|
-
MIT License. See [LICENSE.txt](LICENSE.txt) for details.
|
|
230
|
+
MIT License. See [LICENSE.txt](LICENSE.txt) for details.
|
data/lefthook.yml
ADDED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "forwardable"
|
|
5
|
+
require "open3"
|
|
6
|
+
|
|
3
7
|
module FFmpegCore
|
|
4
8
|
# Configuration for FFmpegCore library
|
|
5
9
|
class Configuration
|
|
@@ -11,8 +15,30 @@ module FFmpegCore
|
|
|
11
15
|
@timeout = 30 # seconds
|
|
12
16
|
end
|
|
13
17
|
|
|
18
|
+
def encoders
|
|
19
|
+
@encoders ||= detect_encoders
|
|
20
|
+
end
|
|
21
|
+
|
|
14
22
|
private
|
|
15
23
|
|
|
24
|
+
def detect_encoders
|
|
25
|
+
return Set.new unless @ffmpeg_binary
|
|
26
|
+
|
|
27
|
+
stdout, _stderr, status = Open3.capture3(@ffmpeg_binary, "-encoders")
|
|
28
|
+
return Set.new unless status.success?
|
|
29
|
+
|
|
30
|
+
encoders = Set.new
|
|
31
|
+
stdout.each_line do |line|
|
|
32
|
+
# Match lines like: " V..... libx264 ..."
|
|
33
|
+
if line =~ /^\s*[VAS][\w.]+\s+(\w+)/
|
|
34
|
+
encoders.add($1)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
encoders
|
|
38
|
+
rescue
|
|
39
|
+
Set.new
|
|
40
|
+
end
|
|
41
|
+
|
|
16
42
|
def detect_binary(name)
|
|
17
43
|
# Check common locations
|
|
18
44
|
paths = ENV["PATH"].split(File::PATH_SEPARATOR)
|
data/lib/ffmpeg_core/movie.rb
CHANGED
|
@@ -26,6 +26,9 @@ module FFmpegCore
|
|
|
26
26
|
# @option options [String, Integer] :audio_bitrate Audio bitrate (e.g., "128k" or 128)
|
|
27
27
|
# @option options [String] :resolution Resolution (e.g., "1280x720")
|
|
28
28
|
# @option options [Integer, Float] :frame_rate Frame rate (e.g., 30)
|
|
29
|
+
# @option options [Array<String>, String] :filter_graph Complex filter graph (e.g., ["[0:v]crop=..."])
|
|
30
|
+
# @option options [Array<String>, String] :maps Stream maps (e.g., ["[outv]", "0:a"])
|
|
31
|
+
# @option options [Symbol] :hwaccel Hardware acceleration (:nvenc, :vaapi, :qsv)
|
|
29
32
|
# @option options [Array<String>] :custom Custom FFmpeg flags
|
|
30
33
|
# @yield [Float] Progress ratio (0.0 to 1.0)
|
|
31
34
|
# @return [String] Path to transcoded file
|
data/lib/ffmpeg_core/probe.rb
CHANGED
|
@@ -39,16 +39,32 @@ module FFmpegCore
|
|
|
39
39
|
video_stream&.dig("codec_name")
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
def video_profile
|
|
43
|
+
video_stream&.dig("profile")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def video_level
|
|
47
|
+
video_stream&.dig("level")
|
|
48
|
+
end
|
|
49
|
+
|
|
42
50
|
def audio_codec
|
|
43
51
|
audio_stream&.dig("codec_name")
|
|
44
52
|
end
|
|
45
53
|
|
|
46
54
|
def width
|
|
47
|
-
video_stream&.dig("width")
|
|
55
|
+
val = video_stream&.dig("width")
|
|
56
|
+
return val unless val
|
|
57
|
+
return val if (rotation || 0) % 180 == 0
|
|
58
|
+
|
|
59
|
+
video_stream&.dig("height")
|
|
48
60
|
end
|
|
49
61
|
|
|
50
62
|
def height
|
|
51
|
-
video_stream&.dig("height")
|
|
63
|
+
val = video_stream&.dig("height")
|
|
64
|
+
return val unless val
|
|
65
|
+
return val if (rotation || 0) % 180 == 0
|
|
66
|
+
|
|
67
|
+
video_stream&.dig("width")
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
def frame_rate
|
|
@@ -79,6 +95,10 @@ module FFmpegCore
|
|
|
79
95
|
tags = video_stream.fetch("tags", {})
|
|
80
96
|
return tags["rotate"].to_i if tags["rotate"]
|
|
81
97
|
|
|
98
|
+
# Try side_data_list (common in some newer formats)
|
|
99
|
+
side_data = video_stream.fetch("side_data_list", []).find { |sd| sd.key?("rotation") }
|
|
100
|
+
return side_data["rotation"].to_i if side_data
|
|
101
|
+
|
|
82
102
|
# Default to 0 if not found
|
|
83
103
|
0
|
|
84
104
|
end
|
|
@@ -102,6 +122,8 @@ module FFmpegCore
|
|
|
102
122
|
end
|
|
103
123
|
|
|
104
124
|
def validate_file!
|
|
125
|
+
return if %r{^(https?|rtmp|rtsp)://}.match?(path)
|
|
126
|
+
|
|
105
127
|
raise InvalidInputError, "File does not exist: #{path}" unless File.exist?(path)
|
|
106
128
|
raise InvalidInputError, "File is not readable: #{path}" unless File.readable?(path)
|
|
107
129
|
end
|
|
@@ -25,6 +25,8 @@ module FFmpegCore
|
|
|
25
25
|
private
|
|
26
26
|
|
|
27
27
|
def validate_input!
|
|
28
|
+
return if %r{^(https?|rtmp|rtsp)://}.match?(input_path)
|
|
29
|
+
|
|
28
30
|
raise InvalidInputError, "Input file does not exist: #{input_path}" unless File.exist?(input_path)
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -36,6 +38,9 @@ module FFmpegCore
|
|
|
36
38
|
def build_command
|
|
37
39
|
cmd = [FFmpegCore.configuration.ffmpeg_binary]
|
|
38
40
|
|
|
41
|
+
# Apply HW Accel if requested
|
|
42
|
+
cmd += resolve_hwaccel_codec
|
|
43
|
+
|
|
39
44
|
# Input file
|
|
40
45
|
cmd += ["-i", input_path]
|
|
41
46
|
|
|
@@ -57,8 +62,16 @@ module FFmpegCore
|
|
|
57
62
|
# Frame rate
|
|
58
63
|
cmd += ["-r", options[:frame_rate].to_s] if options[:frame_rate]
|
|
59
64
|
|
|
60
|
-
# Video
|
|
61
|
-
|
|
65
|
+
# Video filters
|
|
66
|
+
video_filters = []
|
|
67
|
+
video_filters << options[:video_filter] if options[:video_filter]
|
|
68
|
+
|
|
69
|
+
if options[:crop]
|
|
70
|
+
crop = options[:crop]
|
|
71
|
+
video_filters << "crop=#{crop[:width]}:#{crop[:height]}:#{crop[:x]}:#{crop[:y]}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
cmd += ["-vf", video_filters.join(",")] unless video_filters.empty?
|
|
62
75
|
|
|
63
76
|
# Audio filter
|
|
64
77
|
cmd += ["-af", options[:audio_filter]] if options[:audio_filter]
|
|
@@ -69,6 +82,21 @@ module FFmpegCore
|
|
|
69
82
|
# Constant Rate Factor (CRF)
|
|
70
83
|
cmd += ["-crf", options[:crf].to_s] if options[:crf]
|
|
71
84
|
|
|
85
|
+
# Filter Complex / Filter Graph
|
|
86
|
+
filter_graph = options[:filter_graph] || options[:filter_complex]
|
|
87
|
+
if filter_graph
|
|
88
|
+
graph_string = filter_graph.is_a?(Array) ? filter_graph.join(";") : filter_graph
|
|
89
|
+
cmd += ["-filter_complex", graph_string]
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Maps
|
|
93
|
+
maps = options[:maps] || options[:map]
|
|
94
|
+
if maps
|
|
95
|
+
Array(maps).each do |map|
|
|
96
|
+
cmd += ["-map", map]
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
72
100
|
# Custom options (array of strings)
|
|
73
101
|
cmd += options[:custom] if options[:custom]
|
|
74
102
|
|
|
@@ -137,5 +165,50 @@ module FFmpegCore
|
|
|
137
165
|
end
|
|
138
166
|
end
|
|
139
167
|
end
|
|
168
|
+
|
|
169
|
+
def resolve_hwaccel_codec
|
|
170
|
+
return [] unless options[:hwaccel]
|
|
171
|
+
|
|
172
|
+
current_codec = options[:video_codec] || "libx264"
|
|
173
|
+
family = detect_codec_family(current_codec)
|
|
174
|
+
return [] unless family
|
|
175
|
+
|
|
176
|
+
hw_type = options[:hwaccel].to_sym
|
|
177
|
+
target_encoder = HW_ENCODERS.dig(family, hw_type)
|
|
178
|
+
|
|
179
|
+
if target_encoder && FFmpegCore.configuration.encoders.include?(target_encoder)
|
|
180
|
+
options[:video_codec] = target_encoder
|
|
181
|
+
return HW_FLAGS[hw_type] || []
|
|
182
|
+
end
|
|
183
|
+
[]
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def detect_codec_family(codec)
|
|
187
|
+
case codec.to_s
|
|
188
|
+
when /x264|h264|avc/i
|
|
189
|
+
:h264
|
|
190
|
+
when /x265|hevc/i
|
|
191
|
+
:hevc
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
HW_FLAGS = {
|
|
196
|
+
vaapi: ["-hwaccel", "vaapi", "-hwaccel_output_format", "vaapi"],
|
|
197
|
+
qsv: ["-hwaccel", "qsv"],
|
|
198
|
+
nvenc: ["-hwaccel", "cuda", "-hwaccel_output_format", "cuda"]
|
|
199
|
+
}.freeze
|
|
200
|
+
|
|
201
|
+
HW_ENCODERS = {
|
|
202
|
+
h264: {
|
|
203
|
+
nvenc: "h264_nvenc",
|
|
204
|
+
vaapi: "h264_vaapi",
|
|
205
|
+
qsv: "h264_qsv"
|
|
206
|
+
},
|
|
207
|
+
hevc: {
|
|
208
|
+
nvenc: "hevc_nvenc",
|
|
209
|
+
vaapi: "hevc_vaapi",
|
|
210
|
+
qsv: "hevc_qsv"
|
|
211
|
+
}
|
|
212
|
+
}.freeze
|
|
140
213
|
end
|
|
141
214
|
end
|
data/lib/ffmpeg_core/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ffmpeg_core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexey Poimtsev
|
|
@@ -21,6 +21,7 @@ files:
|
|
|
21
21
|
- LICENSE.txt
|
|
22
22
|
- README.md
|
|
23
23
|
- Rakefile
|
|
24
|
+
- lefthook.yml
|
|
24
25
|
- lib/ffmpeg_core.rb
|
|
25
26
|
- lib/ffmpeg_core/configuration.rb
|
|
26
27
|
- lib/ffmpeg_core/errors.rb
|
|
@@ -52,7 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
52
53
|
- !ruby/object:Gem::Version
|
|
53
54
|
version: '0'
|
|
54
55
|
requirements: []
|
|
55
|
-
rubygems_version: 4.0.
|
|
56
|
+
rubygems_version: 4.0.4
|
|
56
57
|
specification_version: 4
|
|
57
58
|
summary: Modern Ruby wrapper for FFmpeg
|
|
58
59
|
test_files: []
|