class MultimediaParadise::CutAudio
Constants
- ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG
- CREATE_A_LOG_FILE
#¶ ↑
CREATE_A_LOG_FILE
¶ ↑If this constant is true then we will create a log file.
#¶ ↑
- DEFAULT_INPUT_FILE
#¶ ↑
DEFAULT_INPUT_FILE
¶ ↑#¶ ↑
- FILE_LAST_USED
#¶ ↑
FILE_LAST_USED
¶ ↑#¶ ↑
- IS_READLINE_AVAILABLE
- NAMESPACE
#¶ ↑
NAMESPACE
¶ ↑#¶ ↑
- PROMPT_TO_USE
#¶ ↑
PROMPT_TO_USE
¶ ↑#¶ ↑
- USE_THIS_PLAYER
#¶ ↑
USE_THIS_PLAYER
¶ ↑Which audio/video player to use for audio-playback.
By default we will use the player set on the toplevel
MultimediaParadise
namespace.This constant will then return e. g. a String such as “mpv”.
#¶ ↑
Public Class Methods
#¶ ↑
MultimediaParadise::CutMultimedia
[]¶ ↑
This class-method also allows some extra instructions such as to limit the duration.
Example:
MultimediaParadise::CutMultimedia['*.mp3', '60 seconds']
This will fetch all .mp3 files.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1468 def self.[]( i, optional_limitation_of_duration = nil ) if i.is_a? String and i.include?('*') i = Dir[i] # This performs a glob, essentially. end if i.is_a? Array # ===================================================================== # # Work in batch-processing mode in this case. # ===================================================================== # if optional_limitation_of_duration and optional_limitation_of_duration.include?('seconds') i.each {|entry| _ = self.new(entry, :do_not_run_yet) _.set_start_at 0 _.set_end_at( optional_limitation_of_duration.to_s.gsub(/seconds/,'').strip.to_f ) _.cut } end else new(i, :run_interactive) end end
#¶ ↑
MultimediaParadise::CutMultimedia.evaluate_from_this_file
¶ ↑
This method can be used to read from a local file and use this file as batch-instruction to cut at the specified position.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb, line 25 def self.evaluate_from_this_file(i) if i.is_a? Array i = i.first end i = i.to_s if File.exist? i file_content = File.readlines(i).map {|inner_line| inner_line.strip.delete(' ') }.reject {|line| line.start_with?('#') or line.strip.empty? # Ignore comments and empty lines. } all_multimedia_files = Dir['*'] - [i] sample = all_multimedia_files.sample _ = MultimediaParadise::CutMultimedia.new(nil, :dont_run_yet) _.set_work_on_this_file(sample) _.interactive_menu(file_content) _.do_cut # ===================================================================== # # Next, merge these files: # ===================================================================== # files_to_be_merged = Dir['cutted_*'] result = MultimediaParadise.merge(files_to_be_merged) if File.exist? result MultimediaParadise.e 'Converting to .wav, then converting back to .mp3.' MultimediaParadise.esystem 'lame --decode -v '+result FileUtils.mv( result.delete_suffix(File.extname(result))+'.wav', 'new_file.wav' ) result = MultimediaParadise::Audio::WavToMp3.new('new_file.wav') if File.exist? 'new_file.mp3' MultimediaParadise.e 'The (new) file can be found at: '+ File.absolute_path('new_file.mp3') # ================================================================= # # And do some clean-up actions in this case: # ================================================================= # File.delete('new_file.wav') if File.exist? 'new_file.wav' File.delete('output.mp3') if File.exist? 'output.mp3' Dir['cutted_*'].each {|this_file| File.delete(this_file) } else MultimediaParadise.e 'No file exists at new_file.mp3.' end end else MultimediaParadise.e 'No file exists at '+sfile(i)+'.' end end
#¶ ↑
initialize¶ ↑
The very first argument to this class should be location to the file that you may want to edit.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 135 def initialize( commandline_arguments = nil, run_already = true ) register_sigint reset # ======================================================================= # # First handle special Symbols given to this class. # ======================================================================= # case commandline_arguments when :interactive, :run_interactive set_interactive_mode_then_enter_interactive_mode end if commandline_arguments and commandline_arguments.is_a?(Array) and commandline_arguments.empty? commandline_arguments << DEFAULT_INPUT_FILE end set_commandline_arguments( commandline_arguments ) # ======================================================================= # # === Handle blocks next # ======================================================================= # if block_given? yielded = yield case yielded # ===================================================================== # # === :gui # ===================================================================== # when :gui @usage_mode = :gui end end # ======================================================================= # # Next check whether a file exists, before we enter the interactive # part potentially. # ======================================================================= # check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file # ======================================================================= # # The following check must happen before we invoke set_file() # because set_file may also exit the program. This is not # deserved when we run the program in interactive mode. # ======================================================================= # case run_already # ======================================================================= # # === :dont_run_yet # ======================================================================= # when :dont_run_yet, :do_not_run_yet run_already = false # ======================================================================= # # === :interactive # ======================================================================= # when :interactive, :run_interactive set_interactive_mode_then_enter_interactive_mode run_already = false end run if run_already end
Public Instance Methods
#¶ ↑
append_the_user_input_onto_the_history
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 870 def append_the_user_input_onto_the_history( i = @user_input ) # ======================================================================= # # Keep track of the input-history next. # ======================================================================= # @array_input_history << i if i end
#¶ ↑
array_all_start_positions?¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1104 def array_all_start_positions? @array_all_start_positions end
#¶ ↑
build_ffmpeg_command
¶ ↑
This method will build the proper ffmpeg command.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1567 def build_ffmpeg_command( # Assemble the FFMPEG main string here. this_file = main_file?, duration = duration? ) ensure_that_there_is_at_least_one_end_position # ======================================================================= # # Next, we must ensure that the @array_all_end_positions is never nil. # ======================================================================= # ensure_that_array_cut_end_is_valid # ======================================================================= # # Merge it all into one Array. # ======================================================================= # merged_array = all_start_positions?.zip(all_end_positions?) # ======================================================================= # # Iterate over that Array next. # ======================================================================= # merged_array.each {|entry| the_start_position = entry.first # Grab the first entry. the_end_position = entry[1] # Grab the second entry. the_end_position = duration.to_f if the_end_position.to_f > duration.to_f # ===================================================================== # # the_end position should never be nil at this point. # ===================================================================== # @t.set_start_position = the_start_position @t.set_end_position = the_end_position e 'Now cutting multimedia-file '+sfancy('`'+this_file+'`')+ ', starting at' e "position #{simp(the_start_position.to_s)} and ending at "\ "position #{simp(the_end_position.to_s)}:" e # ===================================================================== # # Label our output file properly, by prepending the word "cutted_", # the start position and the end position. # ===================================================================== # output_file = 'cutted_'+the_start_position.to_s+ '-'+the_end_position.to_s+'_seconds_'+ File.basename(this_file) set_output_file(output_file) # ===================================================================== # # === Does the output file exist # # Check whether the output file exists or whether it does not. # ===================================================================== # if File.exist? output_file?.to_s e "File `#{sfile(output_file?)}` already exists." e 'We will remove it before continuing.' remove(output_file?) end # ===================================================================== # # Next, build up the ffmpeg command. # ===================================================================== # if this_file.include? ' ' this_file = '"'+this_file+'"' end difference_in_seconds = the_end_position.to_f - the_start_position.to_f the_start_position = @t.convert_to_long_format(the_start_position) # ===================================================================== # # Ok, here we start the real ffmpeg command. # ===================================================================== # _ = 'ffmpeg -i '.dup _ << this_file+' ' _ << '-acodec copy ' # This will copy. See Stackoverflow here: http://stackoverflow.com/a/44032/722915 if is_video_file?(this_file) _ << '-vcodec copy ' end _ << '-ss '+ the_start_position _ << ' -t '+ @t.convert_to_long_format(difference_in_seconds)+ ' '+output_file?.to_s # Relies on ffmpeg. # ===================================================================== # # Next, determine whether we will log into a text file or whether # we will not. # ===================================================================== # if create_log_file? output_file = output_file.dup if output_file.frozen? output_file << '.md' log_cut_action(@t.start?, @t.end?, _, output_file) end cliner e e steelblue(_) # Feedback the command we will use to the user here. e cliner e # And a newline too. system _ } end
#¶ ↑
check_whether_ffmpeg_is_installed
¶ ↑
We have to check whether the user has ffmpeg installed. Because if ffmpeg is unavailable, then cut_audio will not work.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1537 def check_whether_ffmpeg_is_installed _ = ARRAY_LOCATIONS_TO_CHECK_FOR_FFMPEG is_ffmpeg_installed = false _.each {|path| is_ffmpeg_installed = true if File.exist? path+'ffmpeg' } unless is_ffmpeg_installed opnn { :no_trailing_colon }; e e e ' FFmpeg is not installed or could not be found. Please '\ 'install it.' e e ' The class CutMultimedia, part of the MultimediaParadise namespace,' e ' currently requires that ffmpeg is installed.' e e ' The following paths were checked for the availability of ffmpeg:' e _.each {|this_path| e " #{sfancy(this_path)}" } # exit_properly end return is_ffmpeg_installed end
#¶ ↑
check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1939 def check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file( i = commandline_arguments? ) if i.is_a? Array i.each {|entry| check_whether_the_commandline_arguments_contain_a_file_and_assign_this_as_the_main_file(entry) } else if i and File.exist?(i) # =================================================================== # # Designate this as the new file to work with, on startup of # this class. # =================================================================== # set_work_on_this_file(i) end end end
#¶ ↑
chop_into_segments_of_n_seconds_size
¶ ↑
Use this method if you wish to chop the input into different sizes, based on seconds.
Invocation example:
chop 300
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1356 def chop_into_segments_of_n_seconds_size(n_seconds = 60) # 60 seconds by default. n_seconds = n_seconds.first.to_f if n_seconds.is_a? Array e "Now chopping up into segments of `#{sfancy(n_seconds.to_s)}"\ "` seconds duration." ::MultimediaParadise.chop_into_segments_of_n_seconds_size( main_file?, n_seconds ) end
#¶ ↑
chop_off
¶ ↑
Use this method if you want to chop off some seconds from a song, for instance, to get rid of the last 3 seconds of a song.
The argument passed will be assumed to be the number of seconds that you wish to chop off from an audio file - starting from the end.
So, chop_off
(3) simply means to chop off the last 3 seconds.
Usage example:
chop off 3 seconds chop_off 3
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1309 def chop_off(i = 1) if i.is_a? Array i << 1 if i.empty? i = i.join(' ') end i = i.to_s.strip.to_f # We need to strip the input here. And use a Float. # ======================================================================= # # Deduct the input from the end position. We either use the # duration, or the last entry. # ======================================================================= # if duration? if end_position? and end_position?.empty? the_end_position = duration?.to_f - i else # else it is not empty last_position = end_positions?.pop.to_f the_end_position = last_position - i end if no_start_point_was_defined_yet? set_start(0, :be_silent) # Only set a start point if we do not have defined one yet. end set_end(the_end_position, :be_silent) e "We will chop off the last #{simp(i.to_s)} seconds." notify_user_that_he_could_commit_now else e 'No duration was set. Can not chop off anything.' end end
#¶ ↑
chop_off_the_first_n_minutes
¶ ↑
This method can be used to chop away the first n minutes of an audio track. This may be useful if you have some audio-recording of a lecture, and you already know the beginning part, so you quickly chop it away.
Invocation examples:
7min 13min
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1236 def chop_off_the_first_n_minutes( n_minutes = 5 ) n_seconds = n_minutes.to_f * 60 set_start_point(n_seconds) set_end_point(:to_the_end) do_cut_the_multimedia_file end
#¶ ↑
create_a_log_file?¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 908 def create_a_log_file? @create_a_log_file end
#¶ ↑
define_end_point
¶ ↑
This method can be used to set the end point of an audio file, as to where we will stop to cut. For example, an end point of “5” is assumed to mean a cut point at 5 seconds.
set_end
() is an alias to this method.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1836 def define_end_point( i, be_verbose = true ) be_verbose = false if be_verbose == :be_silent i = i.first if i.is_a? Array if i.is_a? Symbol case i when :end_of_the_file, :to_the_end i = length_of_audio_file? end end i = i.to_s.strip # We require a String past this point here. i[0,3] = '' if i.start_with? 'end' i[0,1] = '' if i.start_with? 'e' i = sanitize(i) if i.empty? e "Won't append empty end points." elsif i.include? '%' # User requested percentage-based manipulation. i = ((duration? * (i.delete('%').to_i)) / 100) define_end_point(i) # Recursive call again. else # ===================================================================== # # Convert into seconds if it includes a ':'. # ===================================================================== # if i.include?(':') and Object.const_defined?(:HoursToSeconds) i = HoursToSeconds[i, :be_quiet] end # ===================================================================== # # Until 19.04.2019 we had the following code to detect a logic error, # but it was then realized that not all numbers constitute a logic # error, so this was removed again. # # if i.to_f < starting_position?.to_f # e 'This input ('+sfancy(i.to_s)+') must be invalid because '\ # 'it is' # e 'smaller than the starting position.' # return # end # ===================================================================== # # ===================================================================== # # === Check for too long size given # # The following code has been added at 31.08.2019. If i is larger # than the length of the audio file then we will notify the user # about it, then set it to the maximum length instead. # # This, however had, only makes sense if the length is larger # than 0, hence the double-check below. # ===================================================================== # length_of_audio_file = length_of_audio_file?.to_f if (length_of_audio_file.to_f > 0) and (i.to_f > length_of_audio_file.to_f) e "Note that #{sfancy(i)} is larger than the length of the audio file." e "This is of little practical use, so the input here been reset" e "to the maximum length instead (#{length_of_audio_file} seconds)." i = length_of_audio_file.to_f end end_positions? << i if be_verbose e "Setting an end point at: #{simp(i)}" feedback_all_end_points end end end
#¶ ↑
define_start_point
(set_start
tag)¶ ↑
This method will define a start position, at which we will start to cut an audio file.
set_start
is an alias to this method.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1794 def define_start_point( i, be_verbose = true ) case be_verbose when :be_silent be_verbose = false end i = i.first if i.is_a? Array i = i.to_s.strip i[0,5] = '' if i.start_with? 'start' i[0,1] = '' if i.start_with? 's' i = sanitize(i) if i.empty? e "Won't append empty start points." elsif i.include? '%' # User requested percentage-based manipulation here. i = ((duration? * (i.delete('%').to_i)) / 100) define_start_point(i) # Call itself again. else # ===================================================================== # # Simply append to our main Array. # ===================================================================== # @array_all_start_positions << i.to_f # Store as float. if be_verbose e "#{rev}Setting a start point at: #{simp(i)}" feedback_all_start_points end end end
#¶ ↑
delete_individual_audio_files
¶ ↑
This will delete
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1130 def delete_individual_audio_files _ = output_file? if _.empty? opne 'Nothing to delete.' else _ = _.join(', ') if _.is_a? Array if File.exist? _ opne "Next deleting the file `#{sfile(_)}`." delete(_) else opnn; no_file_exists_at(_) end end end
#¶ ↑
delete_the_original_file
¶ ↑
This method will remove the original file.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1262 def delete_the_original_file( i = work_on_which_file? ) unless i opnn; no_file_exists return end _ = File.basename(i) if i if i and File.exist?(_) opne 'Now deleting the original file at '+sfile(_)+'.' remove_file(_) else opnn; no_file_exists_at(_) end end
#¶ ↑
determine_the_duration
¶ ↑
Set @duration here.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 428 def determine_the_duration( i = main_file? ) # This will determine the ivar @duration. @duration = MultimediaParadise::FileDuration.new(i) { :be_quiet } # Also get the duration of the file here. return @duration.duration? # This should return the duration in question, as a Float. end
#¶ ↑
determine_the_output_file
¶ ↑
This method will determine the output file based on the input file.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1909 def determine_the_output_file( i = input_file? ) i = File.basename(i).dup i.prepend('OUTPUT_FILE_') unless i.start_with?('OUTPUT_FILE_') i = File.absolute_path(i) set_output_file(i) end
#¶ ↑
do_cut_the_multimedia_file
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1999 def do_cut_the_multimedia_file start_cutting report_that_we_are_finished_now return absolute_path_of_the_output_file? end
#¶ ↑
do_reset_all_values_to_their_default_values
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1094 def do_reset_all_values_to_their_default_values opne 'Resetting all values to their defaults again.' _ = file? # Obtain a reference to the old file. reset # Then reset it. set_file(_) end
#¶ ↑
do_the_cutting
¶ ↑
This will cut our audio file.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1208 def do_the_cutting(optional_input = nil) build_ffmpeg_command end
#¶ ↑
end_position= (end tag)¶ ↑
Usage example:
self.end_position = 5
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1117 def end_position=(i = 1000) case i when :end # special instruction then i = duration?.to_f end all_end_positions?[0,0] = i.to_i end
#¶ ↑
ensure_that_array_cut_end_is_valid
¶ ↑
The end positions should always be valid.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 338 def ensure_that_array_cut_end_is_valid(i = duration?) if end_positions?.empty? # We must ensure that it has the length. set_length(i) end end
#¶ ↑
ensure_that_there_is_at_least_one_end_position
¶ ↑
This method will make sure that the end-array has at least one entry.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1777 def ensure_that_there_is_at_least_one_end_position if end_positions?.empty? e 'Note that there is no end position designated yet for '\ 'this file. We will thus set' e 'one to the end position of the audio file.' set_end :end_of_the_file end end
#¶ ↑
enter_the_main_loop
¶ ↑
The main loop is only to be entered if we are in interactive mode. The GUI
in ruby-gtk3 will handle a loop on its own.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1438 def enter_the_main_loop loop { display_the_prompt_in_use_to_the_user obtain_user_input append_the_user_input_onto_the_history interactive_menu # Feed the input in the interactive menu here. break if @may_we_exit } end
#¶ ↑
feedback_start_cutting_at
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 574 def feedback_start_cutting_at here = all_start_positions? if here.empty? e 'No start positions have been determined yet.' else e 'We will start cutting at '+ simp(here.first.to_s)+' seconds.' end end
#¶ ↑
initialize_twentyfour_hours_notation_object
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1659 def initialize_twentyfour_hours_notation_object begin require 'roebe/classes/twentyfour_hours_notation.rb' rescue LoadError; end if Object.const_defined?(:Roebe) and Roebe.const_defined?(:TwentyfourHoursNotation) @t = Roebe::TwentyfourHoursNotation.new # bl $RUBY_TIME/twentyfour_hours_notation.rb else e 'The twentyfour_hours_notation class, part of the roebe gem, '\ 'appears to be unavailable.' e e 'Please consider installing it, such as via:' e e ' gem install roebe' e end end
#¶ ↑
intersect¶ ↑
This method will cut out some middle/central part from a .mp3 file.
Usage example:
intersect 29:23-29:45 intersect 11:20-15:45
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 697 def intersect(i) i = i.first if i.is_a? Array unless main_file? opne 'Please assign a valid, existing file.' return end if i.include? '-' # Ok, then we can split there. splitted = i.split '-' first, last = *splitted # ===================================================================== # # Next, we must convert these numbers into seconds, if it includes # at least one ':' character. # ===================================================================== # if first.include? ':' first.prepend '00:' if first.count(':') == 1 first = HoursToSeconds[first, :be_silent].to_s last.prepend '00:' if last.count(':') == 1 last = HoursToSeconds[last, :be_silent].to_s end # ===================================================================== # # === Operate on the leading segment first: # ===================================================================== # e '(1) We will next chop out the leading segment:' clear_setpoints set_start(0) set_end(first) do_cut clear_setpoints # ===================================================================== # # === Operater on the trailing segment next: # ===================================================================== # e '(2) We will next chop out the trailing segment:' set_start(last) set_end(return_end_of_file_in_seconds) do_cut clear_setpoints end store_here = "MERGED_FILES_#{input_file?}" # Where to store the merged files. merge( output_files?, store_here ) if File.exist? store_here opne "The file should now exist at #{sfile(store_here)}." remove(output_files?) end end
#¶ ↑
left_chop_off
¶ ↑
This method will chop off to the left side of an audio file.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1370 def left_chop_off(i) i = i.join(' ').to_s.strip if i.is_a? Array set_start(i) if no_end_point_was_defined_yet? set_end(duration?, :be_silent) # Only set a start point if we do not have defined one yet. end notify_user_that_he_could_commit_now end
#¶ ↑
log_cut_action
¶ ↑
We will only create a log file if @create_log_file is true.
This method requires four arguments.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1047 def log_cut_action( start_position, end_position, command_that_was_used, output_file ) append_what_into( 'Start position: '+start_position.to_s+N, output_file) append_what_into( 'End position: '+end_position.to_s+N, output_file) append_what_into( 'Command that was used:'+N+' '+command_that_was_used.to_s+N, output_file) end
#¶ ↑
merge_created_files
(merge tag)¶ ↑
This will merge the various audio files.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1179 def merge_created_files if output_files?.size > 1 output_file = 'merged_audio_files_'+ output_file?. sub(/\.mp3$/,'')+'.mp3' e 'Next merging the '+sfancy(output_files?.size.to_s)+ ' files into '+sfile(output_file)+'.' merge_these_files(@array_output_files, output_file) if File.exist? output_file e; cliner { e 'We created a new file at `'+sfile(output_file)+'`.' e 'You can input the command "'+simp('mpl')+'" or "'+ simp('play')+'" to play this new file.' set_main_file(output_file) }; e else e 'The file at `'+sfile(output_file)+'` does not exist.' end else e 'You seem to have specified only one file ('+sfile(file?)+').' e 'We need at least two files for the merge action though.' end end
#¶ ↑
merge_these_files
(merge tag)¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1148 def merge_these_files( array = @array_output_files, output_file = nil ) if array.respond_to? :join array = array.join('\|') output_file = 'GENERIC_OUTPUT_FILE_'+input? if output_file.nil? cmd = 'ffmpeg -i concat:'+array+' -acodec copy '+output_file.to_s esystem cmd else e 'The input to the method merge_these_files() was not correct.' e 'Its class is: '+sfancy(array.class) end end
#¶ ↑
modify_the_main_file_by_prepending_the_upcased_string_done_to_it
¶ ↑
The point of this method is to mark an audio file as “done”.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 300 def modify_the_main_file_by_prepending_the_upcased_string_done_to_it( from = @work_on_this_file, to = "DONE_#{@work_on_this_file}" ) if from.include? '/' # ===================================================================== # # In this case, the above won't work, so we must use another approach. # ===================================================================== # splitted = from.split('/') splitted.last.prepend('DONE_') to = splitted.join('/') end opne "Now renaming #{sfile(from)} to #{sfile(to)}." File.rename(from, to) set_work_on_this_file(to) end
#¶ ↑
notify_the_user_that_interactive_mode_is_ready_now
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1382 def notify_the_user_that_interactive_mode_is_ready_now( this_file = File.basename(work_on_which_file?.to_s) ) # ======================================================================= # # Build up the intro-string. # ======================================================================= # intro = rev+'We are in interactive mode'.dup if File.exist? this_file intro << ', for the file `'+sfile(this_file)+'`.' else intro << '. No file has yet been assigned to work on.'+N intro << 'Use "assign" to assign to a file to work with.' end e intro e e 'You can now start to assign start and end positions' e 'of your file in question. When you are '\ 'done, input '+sfancy('run') e 'to start the cutting. (Remember: Start positions are '\ 'like '+sfancy('s1')+', end' e 'positions are like '+sfancy('e40')+'.)'+N+N e 'You can also use some extra commands, like "'+ simp(:length).to_s+'".' e 'Use "help" to display the help menu.' e N+simp('Hint:').to_s+' You can use '+simp('s11')+ ' and '+simp('e22').to_s+' to denote a start time' e ' at position '+simp('11').to_s+' seconds and an end '\ 'time at position '+simp('22').to_s+' seconds.' e e e 'Input your command next or type "help" for help.' end
#¶ ↑
obtain_user_input
¶ ↑
This method will designate @user_input - in other words it will obtain the user input.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 415 def obtain_user_input if use_readline? @user_input = Readline.readline('', true) else @user_input = $stdin.gets.chomp end end
#¶ ↑
output_file?¶ ↑
This refers to the file that will be created.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1218 def output_file? @output_file end
#¶ ↑
overwrite_old_file
¶ ↑
Note
that when we overwrite the old file, we must re-assign the main file to that file again.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 441 def overwrite_old_file( optional_argument_be_verbose = false ) old_file = output_file? case optional_argument_be_verbose when :be_verbose optional_argument_be_verbose = true end if optional_argument_be_verbose e 'Now overwriting the file `'+sfile(old_file)+'`.' end new_file = input_file? mv(old_file, new_file) assign_file(new_file) # Assign the new file again here. end
#¶ ↑
play_the_audio_file
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 561 def play_the_audio_file(i = file?) if i e "#{Colours.rev}Now playing the assigned "\ "file `#{sfile(i.to_s)}`." esystem("#{MultimediaParadise.player?} #{i}") else e 'No file was found.' end end
#¶ ↑
report_does_the_main_file_exist?¶ ↑
Notify us whether the main file exists or whether it does not.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 899 def report_does_the_main_file_exist? e 'Does the main file exist? '+sfancy( verbose_truth(File.exist?(main_file?.to_s).to_s) ) end
#¶ ↑
report_duration_of_multimedia_file
¶ ↑
This method will report the duration of the multimedia file.
There exists an optional argument called ‘this_file`. If this argument is used, then we will report the duration of that file instead.
feedback_duration
is an alias to this method.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 641 def report_duration_of_multimedia_file( this_file = nil ) use_this_file = file? # Default assignment. use_this_file = this_file if this_file duration = duration? if use_this_file and File.exist?(use_this_file.to_s) # Handle alternative duration. duration = determine_duration(use_this_file) # Calculate the new duration of that file. if duration long_form = '('+Time.at(duration).utc.strftime('%H:%M:%S').to_s+')' e e 'The duration of the file '+sfile(use_this_file)+' is: ' e e simp(" #{duration} seconds #{long_form}") e end else report_no_file_is_assigned end end
#¶ ↑
report_points
¶ ↑
This method can be used to report all start and end positions.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 803 def report_points unless all_start_positions?.empty? e simp('Startpoints')+' for cutting:' print ' '; pp all_start_positions? end unless all_end_positions?.empty? e simp('Endpoints')+' for cutting:' print ' '; pp all_end_positions? end # ======================================================================= # # Next check whether both are empty. # ======================================================================= # if all_end_positions?.empty? and all_start_positions?.empty? e 'It seems as if you have not yet determined any boundaries '\ 'as to where to cut at, yet.' end end
#¶ ↑
report_that_we_are_finished_now
¶ ↑
This method will notify the user that we have finished cutting our audio files.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 750 def report_that_we_are_finished_now( shall_we_report_errors = true ) case shall_we_report_errors when :no_error_reporting shall_we_report_errors = false end e 'We have finished cutting our audio files now.' e _ = output_file? if _.nil? e 'No output file was assigned.' return end if _.include?(' ') # Handle ' ' characters. if _.start_with? '"' and _.end_with? '"' _ = _[1..-2] end end if File.exist?(_) and !File.zero?(_) output_files = [output_files?].flatten.compact if output_files.size > 1 e 'The output files should now be available at:' output_files.each {|file| e " #{sfile(file)}" } e 'If you want to merge these above-listed files together, '\ 'input "merge".' else # Else just one file. # =================================================================== # # Report the duration of that new file. # =================================================================== # report_duration_of_this_file(_) e 'The output file should now be available at:' e e " #{sfile(_)}" e end else if shall_we_report_errors e 'It seems as if something has failed. Please check the '\ 'above output from ffmpeg,' e 'it may be that ffmpeg faced a problem such as missing '\ '.mp3 support.' end end end
#¶ ↑
reset (reset tag)¶ ↑
#¶ ↑
MultimediaParadise::MultimediaBase#reset
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 200 def reset super() # ======================================================================= # # === @namespace # ======================================================================= # @namespace = NAMESPACE # ======================================================================= # # === @toggle # ======================================================================= # @toggle = false # ======================================================================= # # === @user_input # # Set the user input nil on startup. # ======================================================================= # @user_input = nil # ======================================================================= # # === @array_input_history # # Keep the input-history stored in the following Array. # ======================================================================= # @array_input_history = [] # ======================================================================= # # === @we_are_allowed_to_run_system_command # ======================================================================= # @we_are_allowed_to_run_system_command = true # ======================================================================= # # === @work_on_this_file # # This variable will keep track on which file (audio or video) we # will work on for the running instance. It will, once set, # contain the path (a String) to the local file. # ======================================================================= # @work_on_this_file = nil # ======================================================================= # # === @output_file # # We keep track of the output file, so that any possible GUI we may # use also benefits from this. # ======================================================================= # @output_file = nil # ======================================================================= # # === @may_we_exit # ======================================================================= # @may_we_exit = false # ======================================================================= # # === @array_all_start_positions # ======================================================================= # @array_all_start_positions = [] # ======================================================================= # # === @create_a_log_file # # Next determine whether we will create a log file or whether we # will not. # ======================================================================= # @create_a_log_file = CREATE_A_LOG_FILE # ======================================================================= # # === @t # ======================================================================= # @t = nil # ======================================================================= # # === @usage_mode # # This variable can have the following modes: # # :interactive # :gui # # ======================================================================= # @usage_mode = :interactive # ======================================================================= # # Re-set the two main Arrays that keep track of start and end positions # on the assigned main file. # ======================================================================= # clear_setpoints initialize_twentyfour_hours_notation_object end
#¶ ↑
return_end_of_file_in_seconds
¶ ↑
Will always return a String.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 972 def return_end_of_file_in_seconds duration?.to_s end
#¶ ↑
run (run tag)¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1968 def run check_whether_ffmpeg_is_installed # After this point we know that ffmpeg is installed. if File.exist? work_on_which_file?.to_s feedback_duration end # ======================================================================= # # Check against the usage mode. # ======================================================================= # case @usage_mode when :interactive, :default run_in_interactive_mode exit 0 # Signal normal exit. when :gui # Do nothing for now in this event. end end
#¶ ↑
run_in_interactive_mode
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1958 def run_in_interactive_mode try_to_rename_kde_konsole_tab(work_on_which_file?) notify_the_user_that_interactive_mode_is_ready_now enter_the_main_loop end
#¶ ↑
sanitize¶ ↑
This method will sanitize the input that represents time. We want a number to mean “n seconds”.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 369 def sanitize(i) # ======================================================================= # # Simply replace all ',' with '.', in the event the user typed these. # ======================================================================= # i.tr!(',','.') if i.include? ',' # ======================================================================= # # Since as of Dec 2015 we will also check for the input containing # ':' tokens. If so then we assume that the user wants to use # the 24 hours notation such as 05:30, which would mean 5 minutes # and 30 seconds. # ======================================================================= # if i.include? ':' i[0,1] = '' if i.start_with? 'e' # Chop off leading 'e' parts. # ===================================================================== # # The following code will also work for .mp3 files that are longer # than 59:59 seconds. # ===================================================================== # splitted = i.split(':') # Split on all ':' if splitted.size < 3 # =================================================================== # # Prepend 00 in this case. # =================================================================== # splitted[0,0] = '00' end i = splitted.join(':') # ===================================================================== # # Next, convert it into the amount o seconds. # ===================================================================== # i = HoursToSeconds[i, :be_quiet] end return i.to_s # This must always return a String. end
#¶ ↑
set_work_on_this_file
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1679 def set_work_on_this_file( i = :default, also_keep_track_of_which_file_we_will_use = true ) i = i.first if i.is_a? Array # For now we use only the first entry of an Array. case also_keep_track_of_which_file_we_will_use when :do_not_keep_track also_keep_track_of_which_file_we_will_use = false end case i # ======================================================================= # # === --help # ======================================================================= # when /-?-?help/i show_help :then_exit # ======================================================================= # # === :default # # This entry point will cover :default as well as nil-values. # ======================================================================= # when :default, nil i = DEFAULT_INPUT_FILE end # ======================================================================= # # === Make use of the absolute path, if possible # ======================================================================= # unless i.include? '/' i = File.absolute_path(i) end if i and File.file?(i) @work_on_this_file = i # ===================================================================== # # Always set the duration upon assigning a new file to work with. # ===================================================================== # determine_the_duration(i) if File.exist? i # ===================================================================== # # And also always determine the proper output file. # ===================================================================== # determine_the_output_file if also_keep_track_of_which_file_we_will_use and File.exist?(i) # =================================================================== # # We will also keep track of this file in the local filesystem, # if the output directory has been set. # =================================================================== # _ = ::MultimediaParadise.output_directory? unless File.directory? _ mkdir(_) end if _ and File.directory?(_) into = FILE_LAST_USED if is_on_roebe? opne 'Keeping track of the main file in' opne '`'+sfile(into)+'`.' end # =================================================================== # # We must rescue the YAML.dump operation, as it may fail otherwise # sometimes, e. g. via: # # invalid byte sequence in US-ASCII (ArgumentError) # # =================================================================== # begin what = YAML.dump(@work_on_this_file) write_what_into( what, into ) rescue ArgumentError => error pp error pp error.class end end else opne 'File '+sfile(i)+' does not exist.' end end end
#¶ ↑
show_help
(help tag, usage tag)¶ ↑
This method will show the help-options for this class.
To invoke this from the commandline, try:
cut_audio --help
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 987 def show_help( i = main_file?, shall_we_exit = :do_not_exit ) case shall_we_exit when :then_exit shall_we_exit = true else shall_we_exit = false end report_status if File.exist? i.to_s show_invocation_usage e "#{N}The available options for the #{sfancy('CutMultimedia class')}"\ " are:#{green_colour}#{N}#{N}" e eparse ' trim # this will trim from the left-hand '\ 'side of the multimedia-file' eparse ' # ^^^ also known as left-chop or just lchop' eparse ' show_audio_files # show the local audio files' eparse ' report_half_the_duration # report the half-duration of a song' eparse ' report_which_player_we_will_use # report which multimedia-player is in use' eparse ' play # play the currently active song/video file' eparse ' q # q for quit, to exit. Or '\ 'just use "exit" or "quit".' eparse ' feedback # provide some general '\ 'information about this class' eparse ' cut # do the actual cutting' eparse ' disable # dont run system '\ 'command (in case you have to debug something)' eparse ' duration? # show the duration '\ 'of the file in question' eparse ' s[number] # start to cut at this '\ 'start-position in seconds - example: s5' eparse ' e[number] # stop to cut at this end-position' eparse ' play # to use mplayer to '\ 'play that file; p is a shorter alias to it' eparse ' merge # merge the cutted audio files together' eparse ' --last-file # re-use the last file that was used '\ 'in a prior run' eparse ' open # open the file cut_audio.rb in your editor' eparse ' overwrite # overwrite the old file, with the new file' eparse ' points? # feedback all start and end points' eparse ' split # split an audio file into half' eparse ' chop # to chop off some seconds '\ 'from the .mp3 file' eparse ' gui # start the ruby-gtk3 '\ 'widget, a graphical user interface' e e cliner exit_properly if shall_we_exit end
#¶ ↑
show_history
¶ ↑
This method will show the input-history used for CutMultimedia
.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 677 def show_history( i = @array_input_history ) e; i.each_with_index {|command, index| index += 1 e index.to_s.rjust(3)+' '+sfancy(command) }; e end
#¶ ↑
show_how_to_use_intersect
¶ ↑
This method will give the user some hints how to use the intersect part. The intersect part allows us to cut out a middle segment from a .mp3 file.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1422 def show_how_to_use_intersect e 'intersect can be used to chop out middle-segments from an '\ 'audio file.' e e 'The format should be something exactly like this:' e e simp(' intersect 29:23-29:45') e end
#¶ ↑
show_invocation_usage
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 855 def show_invocation_usage if in_commandline_mode? cliner e 'Usage from the commandline:' e e ' cut_multimedia name_of_audio_file_goes_here' e ' cut_multimedia name_of_video_file_goes_here' e cliner end end
#¶ ↑
show_output_files
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 529 def show_output_files( i = @array_output_files ) unless i.empty? e N+'We created these output files:' e end i.each_with_index {|entry, index| entry = entry.to_s index += 1 index = ('('+index.to_s + ')').rjust(4) if entry.start_with? '"' and entry.end_with? '"' entry = entry[1..-2] end e ' '+index+' '+sfancy(entry) }; e end
#¶ ↑
split_audio_file_in_half
¶ ↑
This method will simply split the audio file in half.
To invoke this method, try this command:
split_audio_file_in_half
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 1504 def split_audio_file_in_half( i = main_file? ) if File.exist? i e 'We will next split the audio file `'+sfile(i)+'` in '\ 'half, thus, into two parts.' set_start 0 set_end '50%' cut # Perform the first cut operation here. set_start '50%' set_end '100%' cut # Perform the second cut operation there. # delete_audio_file # Not sure if we should delete it. e 'The audio was split in two equal parts.' else e 'No file called `'+sfile(i)+'` exists.' end end
#¶ ↑
start_position
?¶ ↑
This method depends on the method called array_all_start_positions?.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 290 def start_position? start_positions?.first # For now, always use the first entry. end
#¶ ↑
try_to_use_the_last_file
¶ ↑
This method can be used to re-use the last used file from a prior run.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 618 def try_to_use_the_last_file( i = FILE_LAST_USED ) if File.exist? i set_file( YAML.load_file(i).strip, :do_not_keep_track # <- So to not save into a local .yml file. ) else opnn; no_file_exists_at(i) end end
#¶ ↑
user_did_input_only_numbers
¶ ↑
Simplified start an end point notation.
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 516 def user_did_input_only_numbers(i) @toggle = !@toggle # Toggle it here. case @toggle when true set_start(i) when false set_end(i) end end
Private Instance Methods
#¶ ↑
feedback_cutting
¶ ↑
#¶ ↑
# File lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb, line 825 def feedback_cutting # the verbose variant. e 'We will cut the file '+sfile(work_on_which_file?)+'.' start_cutting_when = 'We will start cutting at '+ sfancy(all_start_positions?.first.to_s)+' seconds.' if all_start_positions?.size > 1 start_cutting_when << ' Additionally we found entries at '+ sfancy(all_start_positions?[1..-1].join(', '))+'.' end e start_cutting_when if !all_end_positions?.empty? end_cutting_when = 'We will end the cutting at '+ sfancy(all_end_positions?.first.to_s)+ ' seconds. ' if all_end_positions?.size > 1 end_cutting_when << ' Additionally we found entries at '+ sfancy(all_end_positions?[1..-1].join(', '))+'.' end e end_cutting_when else e 'We have not yet defined an end position for our file.' e 'You can do this with the command '+sfancy('cut_end')+'.' end duration = all_end_positions?.first.to_i - all_start_positions?.first.to_i e 'The duration of our new file will be '+sfancy( duration.to_s)+' seconds.' if duration? end