media_trim 0.2.1 → 0.2.2
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 +13 -0
- data/README.md +23 -0
- data/lib/media_trim/version.rb +1 -1
- data/lib/media_trim.rb +1 -0
- data/lib/trim_help.rb +5 -0
- data/lib/trim_main.rb +4 -0
- data/lib/trim_preflight.rb +54 -0
- data/lib/trim_run.rb +29 -10
- metadata +4 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 36fc227a339df6b896c637594bf92ce4d433efb4e6c24703132379790f7dfd80
|
|
4
|
+
data.tar.gz: 170d4360b331c7ec5263e729ef8066f0a28bf7e918bbe7c2372a7c9358e4e560
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e9573015fdfb8d2c1abe826171b6962ad98aa3c0ce18cbb1348a52dac132f0d1007c12b14ba9c0f02fe145afe4d851a0463c6600edf38dfdf00b7e3e63b77b40
|
|
7
|
+
data.tar.gz: bc977e7881083631a2f521029ddd3b86b74b1a7ac901f69a78b18aec0370eb37ef8cf21b7085558408bfbeaea8869046904ed8cc2567d227473b0e39fbd8e84c
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
* Added a preflight check that validates the runtime environment before invoking
|
|
6
|
+
`ffmpeg`. The preflight check halts on fatal errors such as a missing `ffmpeg`
|
|
7
|
+
binary, an unreadable input file, a missing software decoder for the input
|
|
8
|
+
codec, or insufficient disk space.
|
|
9
|
+
* Implemented an automatic software-fallback when hardware acceleration
|
|
10
|
+
initialization fails. The tool will warn the user, retry the operation using
|
|
11
|
+
software decoding (which is slower), and only abort if a required software
|
|
12
|
+
decoder or resource is missing.
|
|
13
|
+
* Added a `--no-hwaccel` (`-H`) option to force software decoding and skip
|
|
14
|
+
hardware acceleration.
|
|
15
|
+
|
|
3
16
|
## 0.2.1
|
|
4
17
|
|
|
5
18
|
* Added `spec.platform` to `media_trim.gemspec` because `RubyGems.org` now requires it
|
data/README.md
CHANGED
|
@@ -78,6 +78,29 @@ unless the `-V` option is specified.
|
|
|
78
78
|
* `-f` Overwrite output file if present.
|
|
79
79
|
* `-v` Verbose output.
|
|
80
80
|
* `-V` Do not view the trimmed file when complete.
|
|
81
|
+
* `-H` Disable hardware acceleration and use software decoding. If hardware
|
|
82
|
+
acceleration cannot be initialized on your system, the command will automatically
|
|
83
|
+
retry using software decoding. Software decoding may be slower but will produce
|
|
84
|
+
the same output. If a required software decoder is missing the program will
|
|
85
|
+
halt and display a clear error message.
|
|
86
|
+
|
|
87
|
+
## Preflight checks
|
|
88
|
+
|
|
89
|
+
Before running `ffmpeg` the `trim` command performs a set of preflight checks and
|
|
90
|
+
reports any issues in clear English sentences. The checks include:
|
|
91
|
+
|
|
92
|
+
- Verifying the `ffmpeg` executable is available; if it is not installed the
|
|
93
|
+
command aborts with instructions to install it.
|
|
94
|
+
- Probing hardware acceleration initialization; if hardware acceleration
|
|
95
|
+
initialization fails the tool will warn you and retry in software mode.
|
|
96
|
+
- Verifying that `ffmpeg` can perform a short software decode of the input
|
|
97
|
+
file; if software decoding fails the command will abort as this indicates a
|
|
98
|
+
missing decoder or an unreadable input file.
|
|
99
|
+
- Checking there is sufficient disk space in the destination directory; the
|
|
100
|
+
command aborts if there is not enough free space.
|
|
101
|
+
|
|
102
|
+
These checks ensure the tool halts on fatal problems and otherwise produces a
|
|
103
|
+
successful result using software decoding when needed.
|
|
81
104
|
|
|
82
105
|
|
|
83
106
|
#### Examples
|
data/lib/media_trim/version.rb
CHANGED
data/lib/media_trim.rb
CHANGED
|
@@ -6,6 +6,7 @@ require_relative 'media_trim/version' unless defined? MediaTrimVersion::VERSION
|
|
|
6
6
|
require_relative 'trim_class'
|
|
7
7
|
require_relative 'trim_help'
|
|
8
8
|
require_relative 'trim_main'
|
|
9
|
+
require_relative 'trim_preflight'
|
|
9
10
|
require_relative 'trim_run'
|
|
10
11
|
|
|
11
12
|
if __FILE__ == $PROGRAM_NAME
|
data/lib/trim_help.rb
CHANGED
|
@@ -28,6 +28,11 @@ class MediaTrim
|
|
|
28
28
|
-h Display help information.
|
|
29
29
|
-v Verbose output
|
|
30
30
|
-V Do not view the trimmed file when complete.
|
|
31
|
+
-H Disable hardware acceleration and use software decoding. If hardware
|
|
32
|
+
acceleration initialization fails on your system, the command will
|
|
33
|
+
automatically retry using software decoding. Software decoding is
|
|
34
|
+
slower, but it will produce the same output. If a required software
|
|
35
|
+
decoder is missing then the program will halt with an error.
|
|
31
36
|
|
|
32
37
|
Examples:
|
|
33
38
|
# Crop dir/file.mp4 from 15.0 seconds to the end of the video, save to demo/trim.demo.mp4:
|
data/lib/trim_main.rb
CHANGED
|
@@ -11,6 +11,7 @@ class MediaTrim
|
|
|
11
11
|
@start = MediaTrim.time_format(MediaTrim.to_seconds(start))
|
|
12
12
|
@interval = ['-ss', @start]
|
|
13
13
|
@debug = options[:debug] || false
|
|
14
|
+
@no_hwaccel = options[:no_hwaccel] || false
|
|
14
15
|
|
|
15
16
|
@overwrite = options[:overwrite] ? '-y' : '-n'
|
|
16
17
|
@quiet = options[:quiet].nil? || options[:quiet] ? ['-hide_banner', '-loglevel', 'error', '-nostats'] : []
|
|
@@ -38,6 +39,9 @@ class MediaTrim
|
|
|
38
39
|
opts.on('-d', '--debug', 'Enable debug output') do
|
|
39
40
|
@debug = true
|
|
40
41
|
end
|
|
42
|
+
opts.on('-H', '--no-hwaccel', 'Disable hardware acceleration and use software decoding') do
|
|
43
|
+
@no_hwaccel = true
|
|
44
|
+
end
|
|
41
45
|
end.parse!
|
|
42
46
|
end
|
|
43
47
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'open3'
|
|
2
|
+
require 'shellwords'
|
|
3
|
+
|
|
4
|
+
class MediaTrim
|
|
5
|
+
# Run a set of preflight checks and either exit on fatal errors or
|
|
6
|
+
# return an array of warning messages. The method uses clear, full-sentence
|
|
7
|
+
# messages so the user understands what is missing or degraded.
|
|
8
|
+
def preflight_check(input)
|
|
9
|
+
warnings = []
|
|
10
|
+
|
|
11
|
+
# Check that ffmpeg is installed
|
|
12
|
+
unless system('which ffmpeg > /dev/null 2>&1')
|
|
13
|
+
puts "Fatal: ffmpeg is not installed. Please install ffmpeg and try again.".red
|
|
14
|
+
exit 1
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Probe hardware acceleration initialization in a lightweight way. If
|
|
18
|
+
# this fails with hardware-specific errors we will warn and allow a
|
|
19
|
+
# software retry later. If probing fails for decoding reasons, that is fatal.
|
|
20
|
+
probe_cmd = ['ffmpeg', '-v', 'error', '-hwaccel', 'auto', '-i', input, '-t', '1', '-f', 'null', '-']
|
|
21
|
+
_, stderr, status = Open3.capture3(*probe_cmd)
|
|
22
|
+
|
|
23
|
+
if !status.success?
|
|
24
|
+
hwaccel_errors = [/CUDA_ERROR_NO_DEVICE/, /Failed to initialise VAAPI/, /Cannot open the X11 display/, /Device does not support VK_KHR_video_decode_queue/, /hwaccel/]
|
|
25
|
+
if hwaccel_errors.any? { |rx| stderr =~ rx }
|
|
26
|
+
warnings << "Hardware acceleration could not be initialized: #{stderr.lines.first(2).join(' ').strip}. The command will be retried using software decoding, which is slower but produces the same result."
|
|
27
|
+
else
|
|
28
|
+
# If hw probe fails for other reasons, check software decoding capability.
|
|
29
|
+
sw_cmd = ['ffmpeg', '-v', 'error', '-i', input, '-t', '1', '-f', 'null', '-']
|
|
30
|
+
_, sw_stderr, sw_status = Open3.capture3(*sw_cmd)
|
|
31
|
+
unless sw_status.success?
|
|
32
|
+
puts "Fatal: ffmpeg cannot decode the input file. #{sw_stderr.lines.first(2).join(' ').strip}".red
|
|
33
|
+
exit 1
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Check available disk space in destination directory.
|
|
39
|
+
begin
|
|
40
|
+
dest_dir = Shellwords.escape(File.dirname(input))
|
|
41
|
+
avail = `df --output=avail -B1 #{dest_dir} 2>/dev/null`.lines.last.to_i
|
|
42
|
+
rescue StandardError
|
|
43
|
+
avail = 0
|
|
44
|
+
end
|
|
45
|
+
if avail == 0 || avail < 100_000_000
|
|
46
|
+
puts "Fatal: There is less than 100 MB of free space available in the destination directory. Please free space and try again.".red
|
|
47
|
+
exit 1
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# If we reach here, return any collected warnings for user information.
|
|
51
|
+
warnings.each { |w| puts "Warning: #{w}".yellow }
|
|
52
|
+
warnings
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/trim_run.rb
CHANGED
|
@@ -6,22 +6,41 @@ class MediaTrim
|
|
|
6
6
|
raise TrimError, 'Error: Starting timestamp must be a string'.red unless @start.instance_of? String
|
|
7
7
|
|
|
8
8
|
puts "Trimming '#{@fname}' from #{@start}#{@msg_end}".cyan
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
|
|
10
|
+
# Run preflight checks which may print warnings or exit on fatal errors.
|
|
11
|
+
preflight_warnings = preflight_check @fname
|
|
12
|
+
|
|
13
|
+
# Build ffmpeg command. Respect explicit no-hwaccel option.
|
|
14
|
+
base_args = ['ffmpeg', *@quiet, @overwrite, '-i', @fname, '-acodec', 'aac', *@interval, @copy_filename]
|
|
15
|
+
|
|
16
|
+
if @no_hwaccel
|
|
17
|
+
command = base_args
|
|
18
|
+
else
|
|
19
|
+
command = ['ffmpeg', *@quiet, '-hwaccel', 'auto', @overwrite, '-i', @fname, '-acodec', 'aac', *@interval, @copy_filename]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Execute ffmpeg (timed). If hwaccel was used and failed, retry once without hwaccel.
|
|
18
23
|
start_clock = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
19
24
|
status = system(*command)
|
|
20
25
|
end_clock = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
21
26
|
elapsed = end_clock - start_clock
|
|
22
27
|
puts "Trim took #{MediaTrim.time_format elapsed.to_i}".cyan
|
|
23
28
|
$stdout.flush
|
|
24
|
-
|
|
29
|
+
|
|
30
|
+
unless status
|
|
31
|
+
# If we attempted hwaccel and it failed, retry in software mode once.
|
|
32
|
+
if !@no_hwaccel && command.include?('-hwaccel')
|
|
33
|
+
puts "Warning: hardware acceleration failed. Retrying with software decoding, which may be slower but will produce the correct result.".yellow
|
|
34
|
+
soft_command = base_args
|
|
35
|
+
start_clock = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
36
|
+
status = system(*soft_command)
|
|
37
|
+
end_clock = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
38
|
+
elapsed = end_clock - start_clock
|
|
39
|
+
puts "Retry (software) took #{MediaTrim.time_format elapsed.to_i}".cyan
|
|
40
|
+
$stdout.flush
|
|
41
|
+
end
|
|
42
|
+
exit 1 unless status
|
|
43
|
+
end
|
|
25
44
|
|
|
26
45
|
# View trimmed file unless -q option was specified
|
|
27
46
|
return unless @view
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: media_trim
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mike Slinn
|
|
@@ -80,6 +80,7 @@ files:
|
|
|
80
80
|
- lib/trim_class.rb
|
|
81
81
|
- lib/trim_help.rb
|
|
82
82
|
- lib/trim_main.rb
|
|
83
|
+
- lib/trim_preflight.rb
|
|
83
84
|
- lib/trim_run.rb
|
|
84
85
|
- media_trim.gemspec
|
|
85
86
|
- spec/spec_helper.rb
|
|
@@ -96,7 +97,7 @@ metadata:
|
|
|
96
97
|
source_code_uri: https://github.com/mslinn/media_trim
|
|
97
98
|
post_install_message: |2+
|
|
98
99
|
|
|
99
|
-
Thanks for installing media_trim v0.2.
|
|
100
|
+
Thanks for installing media_trim v0.2.2!
|
|
100
101
|
|
|
101
102
|
rdoc_options: []
|
|
102
103
|
require_paths:
|
|
@@ -112,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
112
113
|
- !ruby/object:Gem::Version
|
|
113
114
|
version: '0'
|
|
114
115
|
requirements: []
|
|
115
|
-
rubygems_version: 4.0.
|
|
116
|
+
rubygems_version: 4.0.19
|
|
116
117
|
specification_version: 4
|
|
117
118
|
summary: Trim an audio or video file using ffmpeg
|
|
118
119
|
test_files: []
|