Class: Helios::Videos::Processors::Mux

Inherits:
Helios::Videos::Processor show all
Defined in:
lib/helios/videos/processors/mux.rb

Instance Attribute Summary

Attributes inherited from Helios::Videos::Processor

#config

Instance Method Summary collapse

Methods inherited from Helios::Videos::Processor

#initialize

Constructor Details

This class inherits a constructor from Helios::Videos::Processor

Instance Method Details

#delete!(video) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/helios/videos/processors/mux.rb', line 79

def delete!(video)
  return unless video.key.present?

  require "mux_ruby"

  MuxRuby.configure do |c|
    c.username = config.mux_token_id
    c.password = config.mux_token_secret
  end

  assets_api = MuxRuby::AssetsApi.new
  assets_api.delete_asset(video.key)
  Rails.logger.info("[helios-videos] Mux asset #{video.key} deleted")
rescue MuxRuby::ApiError => e
  Rails.logger.warn("[helios-videos] Failed to delete Mux asset #{video.key}: #{e.message}")
end

#download_thumbnail!(video, time: "3s") ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/helios/videos/processors/mux.rb', line 138

def download_thumbnail!(video, time: "3s")
  return false unless video.key.present?
  return true if video.thumbnail_image.attached?

  playback_id = extract_playback_id(video)
  return false unless playback_id.present?

  url = "https://image.mux.com/#{playback_id}/thumbnail.jpg?time=#{time.to_i}"

  require "open-uri"
  downloaded_image = URI.open(url)
  video.thumbnail_image.attach(
    io: downloaded_image,
    filename: "video_#{video.id}_thumbnail.jpg",
    content_type: "image/jpeg"
  )
  true
rescue => e
  Rails.logger.error("[helios-videos] Failed to download Mux thumbnail for video #{video.id}: #{e.message}")
  false
end

#download_url(video, expiration: 4.hours) ⇒ Object



128
129
130
131
132
133
134
135
136
# File 'lib/helios/videos/processors/mux.rb', line 128

def download_url(video, expiration: 4.hours)
  return nil unless video.key.present?

  playback_id = extract_playback_id(video)
  return nil unless playback_id.present?

  # Mux provides static renditions at predictable URLs
  "https://stream.mux.com/#{playback_id}/high.mp4"
end

#ingest!(video) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/helios/videos/processors/mux.rb', line 5

def ingest!(video)
  return if video.key.present?
  return unless video.video_file.attached?

  require "mux_ruby"

  MuxRuby.configure do |c|
    c.username = config.mux_token_id
    c.password = config.mux_token_secret
  end

  assets_api = MuxRuby::AssetsApi.new
  input_settings = MuxRuby::InputSettings.new(url: video.video_file.url)
  create_request = MuxRuby::CreateAssetRequest.new(
    input: [input_settings],
    playback_policy: [MuxRuby::PlaybackPolicy::PUBLIC]
  )

  response = assets_api.create_asset(create_request)
  asset = response.data

  video.update!(
    key: asset.id,
    playback_urls: { "hls" => "https://stream.mux.com/#{asset.playback_ids&.first&.id}.m3u8" }
  )

  Rails.logger.info("[helios-videos] Video #{video.id} ingested into Mux: #{video.key}")
end

#ingest_from_url!(video, source_url, provider:) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/helios/videos/processors/mux.rb', line 34

def ingest_from_url!(video, source_url, provider:)
  require "mux_ruby"

  MuxRuby.configure do |c|
    c.username = config.mux_token_id
    c.password = config.mux_token_secret
  end

  assets_api = MuxRuby::AssetsApi.new
  input_settings = MuxRuby::InputSettings.new(url: source_url)
  create_request = MuxRuby::CreateAssetRequest.new(
    input: [input_settings],
    playback_policy: [MuxRuby::PlaybackPolicy::PUBLIC],
    mp4_support: "standard"
  )

  response = assets_api.create_asset(create_request)
  asset = response.data

  video.update!(
    key: asset.id,
    playback_urls: { "hls" => "https://stream.mux.com/#{asset.playback_ids&.first&.id}.m3u8" }
  )

  Rails.logger.info("[helios-videos] Migration: video #{video.id} ingested into Mux: #{video.key}")
end

#playback_url(video, signed: false, expiration: 4.hours) ⇒ Object



96
97
98
99
# File 'lib/helios/videos/processors/mux.rb', line 96

def playback_url(video, signed: false, expiration: 4.hours)
  return nil unless video.key.present?
  video.playback_urls&.dig("hls")
end

#player_component(video, muted: false, expiration: 4.hours) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/helios/videos/processors/mux.rb', line 101

def player_component(video, muted: false, expiration: 4.hours)
  unless video.key.present? && extract_playback_id(video).present?
    return <<~HTML.html_safe
      <div class="text-center p-4 text-muted">
        <div class="spinner-border spinner-border-sm me-2" role="status"></div>
        Processing video...
      </div>
    HTML
  end

  playback_id = extract_playback_id(video)

  <<~HTML.html_safe
    <mux-player
      stream-type="on-demand"
      playback-id="#{playback_id}"
      controls
      #{"muted" if muted}
      style="width: 100%;"
    ></mux-player>
  HTML
end

#ready?(video) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/helios/videos/processors/mux.rb', line 61

def ready?(video)
  return false unless video.key.present?

  require "mux_ruby"

  MuxRuby.configure do |c|
    c.username = config.mux_token_id
    c.password = config.mux_token_secret
  end

  assets_api = MuxRuby::AssetsApi.new
  asset = assets_api.get_asset(video.key)
  asset.data.status == "ready"
rescue => e
  Rails.logger.warn("[helios-videos] Migration: error checking Mux readiness for video #{video.id}: #{e.message}")
  false
end

#signed_token(video, expiration: 4.hours) ⇒ Object



124
125
126
# File 'lib/helios/videos/processors/mux.rb', line 124

def signed_token(video, expiration: 4.hours)
  nil # Mux uses playback IDs, not signed tokens in the same way
end