Module: HLS::Codecs

Defined in:
lib/hls/codecs.rb

Overview

Codec resolution for ffmpeg.

A profile declares its codec in one of three forms:

video_codec :h264                  # logical, auto-resolved per host
video_codec "libx264"              # explicit ffmpeg encoder name
video_codec "h264_nvenc"           # explicit (cloud GPU)

When the profile asks for a logical codec, this module picks the best available encoder for the current host by consulting the ffmpeg encoder list. The list is queried once and cached.

Defined Under Namespace

Classes: UnknownEncoder

Constant Summary collapse

H264 =
{
  videotoolbox: "h264_videotoolbox", # macOS hardware
  nvenc:        "h264_nvenc",        # NVIDIA GPU
  qsv:          "h264_qsv",          # Intel QuickSync
  libx264:      "libx264"            # software fallback
}.freeze
H264_PRIORITY =

Per-platform priority order for the :h264 logical codec. The first encoder available on the host wins.

{
  darwin: [:videotoolbox, :libx264],
  linux:  [:nvenc, :qsv, :libx264]
}.freeze

Class Method Summary collapse

Class Method Details

.available_encodersObject

The set of encoders ffmpeg reports as available on this host. Cached for the life of the process.



54
55
56
# File 'lib/hls/codecs.rb', line 54

def available_encoders
  @available_encoders ||= probe_encoders
end

.platformObject



72
73
74
75
76
77
78
79
# File 'lib/hls/codecs.rb', line 72

def platform
  case RbConfig::CONFIG["host_os"]
  when /darwin/  then :darwin
  when /linux/   then :linux
  when /mswin|mingw|cygwin/ then :windows
  else :unknown
  end
end

.probe_encodersObject



81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/hls/codecs.rb', line 81

def probe_encoders
  stdout, _stderr, status = Open3.capture3("ffmpeg", "-hide_banner", "-encoders")
  return Set.new unless status.success?

  stdout.lines.filter_map do |line|
    # Encoder lines look like:  V..... libx264               ...
    # Skip the header and metadata lines.
    next unless line =~ /\A [\sVAS\.][\sFSXBD\.]{5}\s+(\S+)/

    $1
  end.to_set
end

.reset!Object

Reset the encoder cache. Useful in tests.



59
60
61
# File 'lib/hls/codecs.rb', line 59

def reset!
  @available_encoders = nil
end

.resolve(value) ⇒ Object

Resolves a ‘video_codec` value to an explicit ffmpeg encoder name.



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/hls/codecs.rb', line 38

def resolve(value)
  case value
  when :h264
    resolve_h264
  when Symbol
    # Already a specific variant: :libx264, :nvenc, etc.
    H264.fetch(value) { raise UnknownEncoder, "Unknown codec symbol: #{value}" }
  when String
    value
  else
    raise ArgumentError, "Unsupported video_codec value: #{value.inspect}"
  end
end

.resolve_h264Object



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

def resolve_h264
  priority = H264_PRIORITY[platform] || [:libx264]
  encoder_name = priority
    .map { |sym| H264.fetch(sym) }
    .find { |name| available_encoders.include?(name) }

  encoder_name || "libx264"
end