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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 37f7ed510ad90d35e85ef47e33fabf9d1994779512a6c6b4342c570e3a957048
4
- data.tar.gz: b0f0aed439b2fe793be04f38ea30937a767f53c997bb1723c38d9b2357b23e63
3
+ metadata.gz: 36fc227a339df6b896c637594bf92ce4d433efb4e6c24703132379790f7dfd80
4
+ data.tar.gz: 170d4360b331c7ec5263e729ef8066f0a28bf7e918bbe7c2372a7c9358e4e560
5
5
  SHA512:
6
- metadata.gz: de4ee11b00dfc2067a94f1da192d76940ca09d1baacd8ce3ddb215444a0dd45c1a4aac93c46399432e5818aa76efba4bc2ccadaeb8f51bb317f707b40c8f456f
7
- data.tar.gz: 1bdea1d74ba69994bfaf7452c1fe1fe6cd9b9c9ecb76530c45bfb640c5624ae55456ab3012cb39157778cb5fc4d0532003285285218b3a64702b0035926fbd71
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
@@ -1,3 +1,3 @@
1
1
  module MediaTrimVersion
2
- VERSION = '0.2.1'.freeze
2
+ VERSION = '0.2.2'.freeze
3
3
  end
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
- command = ['ffmpeg',
10
- *@quiet,
11
- '-hwaccel', 'auto',
12
- @overwrite,
13
- '-i', @fname,
14
- '-acodec', 'aac',
15
- *@interval,
16
- @copy_filename]
17
- # puts command.join(' ').yellow
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
- exit 1 unless status
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.1
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.1!
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.16
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: []