Class: Aspera::Preview::Utils

Inherits:
Object
  • Object
show all
Defined in:
lib/aspera/preview/utils.rb

Constant Summary collapse

FFMPEG_DEFAULT_PARAMS =
[
  '-y', # overwrite output without asking
  '-loglevel', 'error' # show only errors and up
].freeze

Class Method Summary collapse

Class Method Details

.check_tools(skip_types = []) ⇒ Object

check that external tools can be executed



34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/aspera/preview/utils.rb', line 34

def check_tools(skip_types=[])
  tools_to_check = EXTERNAL_TOOLS.dup
  tools_to_check.delete(:unoconv) if skip_types.include?(:office)
  # Check for binaries
  tools_to_check.each do |command_sym|
    external_command(command_sym, ['-h'], out: File::NULL)
  rescue Errno::ENOENT => e
    raise "missing #{command_sym} binary: #{e}"
  rescue
    nil
  end
end

.external_capture(command_sym, command_args) ⇒ Object



55
56
57
58
# File 'lib/aspera/preview/utils.rb', line 55

def external_capture(command_sym, command_args)
  Aspera.assert_values(command_sym, EXTERNAL_TOOLS){'command'}
  return Environment.secure_capture(exec: command_sym.to_s, args: command_args.map(&:to_s))
end

.external_command(command_sym, command_args) ⇒ Object

execute external command one could use “system”, but we would need to redirect stdout/err

Returns:

  • nil



50
51
52
53
# File 'lib/aspera/preview/utils.rb', line 50

def external_command(command_sym, command_args)
  Aspera.assert_values(command_sym, EXTERNAL_TOOLS){'command'}
  Environment.secure_execute(exec: command_sym.to_s, args: command_args.map(&:to_s), out: File::NULL, err: File::NULL)
end

.ffmpeg(gl_p: FFMPEG_DEFAULT_PARAMS, in_p: [], in_f:, out_p: [], out_f:) ⇒ Object



60
61
62
63
64
65
# File 'lib/aspera/preview/utils.rb', line 60

def ffmpeg(gl_p: FFMPEG_DEFAULT_PARAMS, in_p: [], in_f:, out_p: [], out_f:)
  Aspera.assert_type(gl_p, Array)
  Aspera.assert_type(in_p, Array)
  Aspera.assert_type(out_p, Array)
  external_command(:ffmpeg, gl_p +  in_p + ['-i', in_f] + out_p + [out_f])
end

.ffmpeg_fmt(temp_folder) ⇒ Object



76
77
78
# File 'lib/aspera/preview/utils.rb', line 76

def ffmpeg_fmt(temp_folder)
  return File.join(temp_folder, TEMP_FORMAT)
end

.get_tmp_num_filepath(temp_folder, file_number) ⇒ Object



80
81
82
# File 'lib/aspera/preview/utils.rb', line 80

def get_tmp_num_filepath(temp_folder, file_number)
  return File.join(temp_folder, format(TEMP_FORMAT, file_number))
end

.shell_quote(argument) ⇒ Object

returns string with single quotes suitable for bash if there is any bash meta-character



27
28
29
30
31
# File 'lib/aspera/preview/utils.rb', line 27

def shell_quote(argument)
  return argument unless argument.chars.any?{ |c| BASH_SPECIAL_CHARACTERS.include?(c)}
  # surround with single quotes, and escape single quotes
  return %Q{'#{argument.gsub("'"){ |_s| %q{'"'"'}}}'}
end

.video_blend_frames(temp_folder, index1, index2) ⇒ Object



91
92
93
94
95
96
97
98
99
100
# File 'lib/aspera/preview/utils.rb', line 91

def video_blend_frames(temp_folder, index1, index2)
  img1 = get_tmp_num_filepath(temp_folder, index1)
  img2 = get_tmp_num_filepath(temp_folder, index2)
  count = index2 - index1 - 1
  1.upto(count) do |i|
    percent = i * 100 / (count + 1)
    filename = get_tmp_num_filepath(temp_folder, index1 + i)
    external_command(:magick, ['composite', '-blend', percent, img2, img1, filename])
  end
end

.video_dump_frame(input_file, offset_seconds, scale, output_file, index = nil) ⇒ Object



102
103
104
105
106
107
108
109
110
# File 'lib/aspera/preview/utils.rb', line 102

def video_dump_frame(input_file, offset_seconds, scale, output_file, index=nil)
  output_file = get_tmp_num_filepath(output_file, index) unless index.nil?
  ffmpeg(
    in_f: input_file,
    in_p: ['-ss', offset_seconds],
    out_f: output_file,
    out_p: ['-frames:v', 1, '-filter:v', "scale=#{scale}"])
  return output_file
end

.video_dupe_frame(temp_folder, index, count) ⇒ Object



84
85
86
87
88
89
# File 'lib/aspera/preview/utils.rb', line 84

def video_dupe_frame(temp_folder, index, count)
  input_file = get_tmp_num_filepath(temp_folder, index)
  1.upto(count) do |i|
    FileUtils.ln_s(input_file, get_tmp_num_filepath(temp_folder, index + i))
  end
end

.video_get_duration(input_file) ⇒ Object

Returns Float in seconds.

Returns:

  • Float in seconds



68
69
70
71
72
73
74
# File 'lib/aspera/preview/utils.rb', line 68

def video_get_duration(input_file)
  return external_capture(:ffprobe, [
    '-loglevel', 'error',
    '-show_entries', 'format=duration',
    '-print_format', 'default=noprint_wrappers=1:nokey=1', # cspell:disable-line
    input_file]).to_f
end