Class: HLS::Input
- Inherits:
-
Object
- Object
- HLS::Input
- 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
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Instance Method Summary collapse
- #bitrate ⇒ Object
- #codec ⇒ Object
- #duration ⇒ Object
-
#framerate ⇒ Object
Frames per second as a Float.
- #height ⇒ Object
-
#initialize(path) ⇒ Input
constructor
A new instance of Input.
- #json ⇒ Object
-
#validate! ⇒ Object
Raises HLS::Error if the input is not a video.
-
#video? ⇒ Boolean
Returns true if ffprobe found a usable video stream.
- #width ⇒ Object
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
#path ⇒ Object (readonly)
Returns the value of attribute path.
24 25 26 |
# File 'lib/hls/input.rb', line 24 def path @path end |
Instance Method Details
#bitrate ⇒ Object
32 |
# File 'lib/hls/input.rb', line 32 def bitrate = video_stream[:bit_rate] |
#codec ⇒ Object
33 |
# File 'lib/hls/input.rb', line 33 def codec = video_stream[:codec_name] |
#duration ⇒ Object
34 |
# File 'lib/hls/input.rb', line 34 def duration = json.dig(:format, :duration)&.to_f |
#framerate ⇒ Object
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 |
#height ⇒ Object
31 |
# File 'lib/hls/input.rb', line 31 def height = video_stream[:height] |
#json ⇒ Object
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.
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.
56 57 58 59 |
# File 'lib/hls/input.rb', line 56 def video? stream = json.dig(:streams, 0) !!(stream && stream[:width] && stream[:height]) end |
#width ⇒ Object
30 |
# File 'lib/hls/input.rb', line 30 def width = video_stream[:width] |