class FFmpegProgress::FFmpeg
The class that does the actual work.
Constants
- DEFAULT_DIR
The directory for the default output file.
- DEFAULT_EXT
The extension for the default output file.
- LOG_FILE
The log file for
ffmpeg
. Progress data will be read from here.
Attributes
Returns the duration (in seconds) of the input file. @return [Integer]
Returns the duration of the input file as a ffmpeg
format string +(HH:MM:SS.ms)+.
@return [Integer]
The input file. @return [String]
The options to pass to ffmpeg
. Any occurrences of the string +_INPUT_+ will be converted to the value of the {#input} attribute. @return [String]
The output file. Directories will be auto-created on execution. @return [String]
The PID of the last spawned ffmpeg
process, or nil
if none spawned yet. @return [Integer]
The theme for the progress bar. See {Theme::DEFAULT_THEME} for details. @return [Hash]
Public Class Methods
Creates a new {FFmpeg} instance.
@param [String] input_file the source file name. @param [Hash] option_hash @option option_hash [String] :output the output file to write to. @option option_hash [String] :options the options to pass to ffmpeg
.
See {#options} for details and {Presets} for examples.
@option option_hash [Hash, Theme] :theme either a theme hash or a {Theme}
object.
@option option_hash [Boolean] :bell whether to play a bell sound upon
finishing the task. (See {Utils} for details.)
@return [FFmpeg]
# File lib/ffmpeg_progress/ffmpeg.rb, line 60 def initialize(input_file, option_hash = {}) self.input = input_file @options = option_hash.fetch :options, DEFAULT_OPTIONS @theme = Theme.from(option_hash.fetch :theme, Theme.new) @bell = option_hash.fetch :bell, false @output = option_hash.fetch :output, @output @duration_ff ||= nil @duration ||= nil @block = nil @pid = nil @last_bar = nil end
Public Instance Methods
Returns the current ffmpeg
command that will be executed by {#run}.
@return [String]
# File lib/ffmpeg_progress/ffmpeg.rb, line 98 def command "ffmpeg -i \'#{@input}\' #{@options} \'#{@output}\' &> #{LOG_FILE}" .gsub('_INPUT_', "'#{@input}'") end
Set the input file.
@param [String] string @return [String]
# File lib/ffmpeg_progress/ffmpeg.rb, line 82 def input=(string) @input = string return @input unless @input @duration_ff = `ffmpeg -i \'#{@input}\' 2>&1`.scan(/..:..:..\.../).first @duration = parse_ffmpeg_time(@duration_ff) @output ||= "#{DEFAULT_DIR}#{@input.rpartition('.').first}.#{DEFAULT_EXT}" @input end
Run ffmpeg
while printing a progress bar to the terminal. If a block is passed, its return value will be attached to the progress bar. The current {FFmpeg} instance will be passed to the block.
@return [0]
# File lib/ffmpeg_progress/ffmpeg.rb, line 109 def run(&block) File.delete(LOG_FILE) if File.exist?(LOG_FILE) FileUtils.mkpath(@output.rpartition('/').first) if output.include?('/') @pid = spawn command @block = block sleep 1 until current_time monitor_progress cleanup 0 end
Private Instance Methods
Kill ffmpeg
if still running, and delete the log file.
# File lib/ffmpeg_progress/ffmpeg.rb, line 161 def cleanup Process.detach(@pid) ffmpeg_alive = begin Process.kill(0, @pid) true rescue Errno::ESRCH false end Process.kill('TERM', @pid) if ffmpeg_alive File.delete(LOG_FILE) if File.exist?(LOG_FILE) end
Get the current time (in ffmpeg
format) from the log file. Returns nil
if the actual transcoding process has not started yet.
@return [String]
# File lib/ffmpeg_progress/ffmpeg.rb, line 152 def current_time return nil unless File.exist?(LOG_FILE) match = File.read(LOG_FILE).scan(/time=..:..:..\.../).last return '00:00:00.00' unless match match.delete('time=') end
Display the progress bar while waiting for ffmpeg
to finish.
# File lib/ffmpeg_progress/ffmpeg.rb, line 128 def monitor_progress until Process.waitpid(@pid, Process::WNOHANG) print "\r#{progress_bar}" sleep 1 end puts "\r#{progress_bar(@duration_ff, finished: true)}" bell if @bell rescue Interrupt, IRB::Abort puts "\r#{progress_bar(current_time, interrupted: true)}" end
Display the progress bar.
# File lib/ffmpeg_progress/ffmpeg.rb, line 141 def progress_bar(time = current_time, option_hash = {}) position = parse_ffmpeg_time(time).to_f / @duration option_hash.merge!(block_output: (@block ? @block.call(self) : nil)) @theme.bar(position, time, option_hash) end