Class: HLS::Input

Inherits:
Object
  • Object
show all
Defined in:
lib/hls/input.rb

Overview

An input video file. Probes its metadata via ffprobe lazily (the first time you ask for ‘width`, `height`, etc.) and caches the result.

Constant Summary collapse

PROBE_ARGS =
%w[
  -v error
  -select_streams v:0
  -show_entries stream
  -show_entries format
  -of json
].freeze
DEFAULT_FRAMERATE =

Fallback framerate when ffprobe doesn’t report one (rare, but possible for some containers / streams). 30fps is the safe choice for web video — common for screencasts and matches most uploads.

30

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Input

Returns a new instance of Input.



26
27
28
# File 'lib/hls/input.rb', line 26

def initialize(path)
  @path = Pathname.new(path)
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



24
25
26
# File 'lib/hls/input.rb', line 24

def path
  @path
end

Instance Method Details

#bitrateObject



32
# File 'lib/hls/input.rb', line 32

def bitrate  = video_stream[:bit_rate]

#codecObject



33
# File 'lib/hls/input.rb', line 33

def codec    = video_stream[:codec_name]

#durationObject



34
# File 'lib/hls/input.rb', line 34

def duration = json.dig(:format, :duration)&.to_f

#framerateObject

Frames per second as a Float. ffprobe reports framerate as a rational (“30000/1001”); we resolve it to a float and round to the nearest int. Returns DEFAULT_FRAMERATE if the input doesn’t advertise a usable framerate.



40
41
42
43
44
45
46
47
# File 'lib/hls/input.rb', line 40

def framerate
  raw = video_stream[:avg_frame_rate] || video_stream[:r_frame_rate]
  return DEFAULT_FRAMERATE if raw.nil? || raw.empty? || raw == "0/0"

  num, den = raw.split("/").map(&:to_f)
  return DEFAULT_FRAMERATE if den.nil? || den.zero?
  (num / den).round
end

#heightObject



31
# File 'lib/hls/input.rb', line 31

def height   = video_stream[:height]

#jsonObject



49
50
51
# File 'lib/hls/input.rb', line 49

def json
  @json ||= probe
end

#validate!Object

Raises HLS::Error if the input is not a video. Call this before handing an Input to the encode pipeline if you want to fail fast with a clear message rather than waiting for ffmpeg to choke.

Raises:



64
65
66
67
68
69
70
# File 'lib/hls/input.rb', line 64

def validate!
  return self if video?
  raise HLS::Error,
    "#{@path} has no video stream — ffprobe found " \
    "#{json[:streams]&.size || 0} stream(s) but none with width/height. " \
    "Audio-only files and non-media files are not supported."
end

#video?Boolean

Returns true if ffprobe found a usable video stream. False for audio-only files, malformed media, or anything missing pixel dimensions.

Returns:

  • (Boolean)


56
57
58
59
# File 'lib/hls/input.rb', line 56

def video?
  stream = json.dig(:streams, 0)
  !!(stream && stream[:width] && stream[:height])
end

#widthObject



30
# File 'lib/hls/input.rb', line 30

def width    = video_stream[:width]