Module: ActiveEncode::EngineAdapters::MediaConvertOutput

Defined in:
lib/active_encode/engine_adapters/media_convert_output.rb

Constant Summary collapse

AUDIO_SETTINGS =
{
  "AAC" => :aac_settings,
  "AC3" => :ac3_settings,
  "AIFF" => :aiff_settings,
  "EAC3_ATMOS" => :eac_3_atmos_settings,
  "EAC3" => :eac_3_settings,
  "MP2" => :mp_2_settings,
  "MP3" => :mp_3_settings,
  "OPUS" => :opus_settings,
  "VORBIS" => :vorbis_settings,
  "WAV" => :wav_settings
}.freeze
VIDEO_SETTINGS =
{
  "AV1" => :av_1_settings,
  "AVC_INTRA" => :avc_intra_settings,
  "FRAME_CAPTURE" => :frame_capture_settings,
  "H_264" => :h264_settings,
  "H_265" => :h265_settings,
  "MPEG2" => :mpeg_2_settings,
  "PRORES" => :prores_settings,
  "VC3" => :vc_3_settings,
  "VP8" => :vp_8_settings,
  "VP9" => :vp_9_settings,
  "XAVC" => :xavc_settings
}.freeze

Class Method Summary collapse

Class Method Details

.construct_output_url(destination:, file_input_url:, name_modifier:, file_suffix:) ⇒ Object

constructs an ‘s3:` output URL from the MediaConvert job params, the same way MediaConvert will.

Examples:

construct_output_filename(
  destination: "s3://bucket/base_name",
  original_filename: "foo.mp3",
  name_modifier: "-1080",
  suffix: "m3u8")
# =>  "s3://bucket/base_name-1080.m3u8"
construct_output_filename(
  destination: "s3://bucket/directory_end_in_slash/",
  original_filename: "original-filename.mp3",
  name_modifier: "-1080",
  suffix: "m3u8")
# =>  "s3://bucket/directory_end_in_slash/original_filename-1080.m3u8"
construct_output_filename(
  destination: "s3://bucket/directory_end_in_slash/",
  original_filename: "original-filename.mp3",
  name_modifier: nil,
  suffix: "m3u8")
# =>  "s3://bucket/directory_end_in_slash/original_filename.m3u8"


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 116

def construct_output_url(destination:, file_input_url:, name_modifier:, file_suffix:)
  output = destination

  # MediaConvert operates such that if you give a destination ending in '/',
  # it'll use the original file name as part of output url.
  if output.end_with?('/')
    # ".*" on the end will strip extension off
    output += File.basename(file_input_url, '.*')
  end

  output += name_modifier if name_modifier

  output += "." + file_suffix

  output
end

.extract_audio_bitrate(settings) ⇒ Object



157
158
159
160
161
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 157

def extract_audio_bitrate(settings)
  codec_settings = extract_audio_codec_settings(settings)
  return nil if codec_settings.nil?
  try(codec_settings, :bitrate)
end

.extract_audio_codec(settings) ⇒ Object



133
134
135
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 133

def extract_audio_codec(settings)
  settings.audio_descriptions&.first&.codec_settings&.codec
end

.extract_audio_codec_settings(settings) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 137

def extract_audio_codec_settings(settings)
  codec = extract_audio_codec(settings)
  return nil if codec.nil?

  codec_key = AUDIO_SETTINGS[codec]
  settings.audio_descriptions.first.codec_settings[codec_key]
end

.extract_video_bitrate(settings) ⇒ Object



163
164
165
166
167
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 163

def extract_video_bitrate(settings)
  codec_settings = extract_video_codec_settings(settings)
  return nil if codec_settings.nil?
  try(codec_settings, :bitrate) || try(codec_settings, :max_bitrate)
end

.extract_video_codec(settings) ⇒ Object



145
146
147
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 145

def extract_video_codec(settings)
  settings.video_description&.codec_settings&.codec
end

.extract_video_codec_settings(settings) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 149

def extract_video_codec_settings(settings)
  codec = extract_video_codec(settings)
  return nil if codec.nil?

  codec_key = VIDEO_SETTINGS[codec]
  settings.video_description.codec_settings[codec_key]
end

.extract_video_frame_rate(settings) ⇒ Object



169
170
171
172
173
174
175
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 169

def extract_video_frame_rate(settings)
  codec_settings = extract_video_codec_settings(settings)
  return nil if codec_settings.nil?
  (codec_settings.framerate_numerator.to_f / codec_settings.framerate_denominator.to_f).round(2)
rescue
  nil
end

.tech_metadata_from_logged(settings, logged_output) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 51

def (settings, logged_output)
  url = logged_output.dig('outputFilePaths', 0)
  {
    width: logged_output.dig('videoDetails', 'widthInPx'),
    height: logged_output.dig('videoDetails', 'heightInPx'),
    frame_rate: extract_video_frame_rate(settings),
    duration: logged_output['durationInMs'],
    audio_codec: extract_audio_codec(settings),
    video_codec: extract_video_codec(settings),
    audio_bitrate: extract_audio_bitrate(settings),
    video_bitrate: extract_video_bitrate(settings),
    url: url,
    suffix: settings.name_modifier
  }
end

.tech_metadata_from_probe(url:, probe_response:, output_settings: nil) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 67

def (url:, probe_response:, output_settings: nil)
  tech_md = { url: url, suffix: output_settings&.name_modifier }
  return tech_md unless probe_response

  # Need to determine which track has video/audio
  video_track = probe_response.container.tracks&.find { |track| track.track_type == "video" }
  audio_track = probe_response.container.tracks&.find { |track| track.track_type == "audio" }
  frame_rate = (video_track.video_properties.frame_rate.numerator / video_track.video_properties.frame_rate.denominator.to_f).round(2) if video_track
  duration = probe_response.container.duration * 1000 if probe_response.container.duration.present?

  tech_md.merge({
                  width: video_track&.video_properties&.width,
                  height: video_track&.video_properties&.height,
                  frame_rate: frame_rate,
                  duration: duration, # milliseconds
                  audio_codec: audio_track&.codec,
                  video_codec: video_track&.codec,
                  audio_bitrate: audio_track&.audio_properties&.bit_rate,
                  video_bitrate: video_track&.video_properties&.bit_rate,
                  file_size: probe_response..file_size
                })
end

.tech_metadata_from_settings(output_url:, output_settings:, output_detail_settings:) ⇒ Object

Parameters:

  • output_url (String)

    url, expected to be ‘s3://`

  • output_settings (Aws::MediaConvert::Types::Output)
  • output_detail_settings (Aws::MediaConvert::Types::OutputDetail)


36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/active_encode/engine_adapters/media_convert_output.rb', line 36

def (output_url:, output_settings:, output_detail_settings:)
  {
    width: output_detail_settings.video_details&.width_in_px,
    height: output_detail_settings.video_details&.height_in_px,
    frame_rate: extract_video_frame_rate(output_settings),
    duration: output_detail_settings.duration_in_ms,
    audio_codec: extract_audio_codec(output_settings),
    video_codec: extract_video_codec(output_settings),
    audio_bitrate: extract_audio_bitrate(output_settings),
    video_bitrate: extract_video_bitrate(output_settings),
    url: output_url,
    suffix: output_settings.name_modifier
  }
end