Class: Cohere::Transcribe::Audio::FFmpegNative::Library
- Inherits:
-
Object
- Object
- Cohere::Transcribe::Audio::FFmpegNative::Library
- Defined in:
- lib/cohere/transcribe/audio/ffmpeg_native.rb
Constant Summary collapse
- FUNCTIONS =
{ probe: [%i[voidp size_t], :int], decode: [%i[voidp int uint64 voidp voidp voidp size_t], :int], duration: [%i[voidp voidp voidp size_t], :int], cancel: [[], :void], free: [[:voidp], :void] }.freeze
- TYPE_MAP =
{ void: Fiddle::TYPE_VOID, voidp: Fiddle::TYPE_VOIDP, int: Fiddle::TYPE_INT, size_t: Fiddle::TYPE_SIZE_T, uint64: Fiddle::TYPE_UINT64_T }.freeze
Instance Attribute Summary collapse
-
#diagnostic ⇒ Object
readonly
Returns the value of attribute diagnostic.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
Class Method Summary collapse
Instance Method Summary collapse
- #cancel_all! ⇒ Object
- #decode(path, sample_rate:, max_decoded_bytes:) ⇒ Object
- #duration(path) ⇒ Object
-
#initialize(path) ⇒ Library
constructor
A new instance of Library.
- #probe! ⇒ Object
Constructor Details
#initialize(path) ⇒ Library
Returns a new instance of Library.
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 89 def initialize(path) @path = path @handle = Fiddle::Handle.new(path, Fiddle::RTLD_NOW) @functions = FUNCTIONS.to_h do |name, (arguments, result)| address = @handle["cohere_audio_ffmpeg_#{name}"] function = Fiddle::Function.new( address, arguments.map { |type| TYPE_MAP.fetch(type) }, TYPE_MAP.fetch(result) ) [name, function] end.freeze end |
Instance Attribute Details
#diagnostic ⇒ Object (readonly)
Returns the value of attribute diagnostic.
87 88 89 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 87 def diagnostic @diagnostic end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
87 88 89 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 87 def path @path end |
Class Method Details
.candidate_paths ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 46 def candidate_paths explicit = ENV.fetch("COHERE_TRANSCRIBE_AUDIO_LIBRARY", nil) return [explicit] if explicit && !explicit.empty? packaged = File.("../native", __dir__) patterns = case RbConfig::CONFIG.fetch("host_os") when /darwin/ then ["libcohere_audio*.dylib"] when /mswin|mingw|cygwin/ then ["cohere_audio*.dll", "libcohere_audio*.dll"] else ["libcohere_audio.so", "libcohere_audio.so.*"] end paths = patterns.flat_map { |pattern| Dir.glob(File.join(packaged, pattern)) }.sort paths.concat(system_library_names) paths.uniq end |
.load ⇒ Object
36 37 38 39 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 36 def load @mutex ||= Mutex.new @mutex.synchronize { @instance ||= load_uncached } end |
.loaded ⇒ Object
41 42 43 44 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 41 def loaded mutex = @mutex mutex&.synchronize { @instance } end |
Instance Method Details
#cancel_all! ⇒ Object
217 218 219 220 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 217 def cancel_all! @functions.fetch(:cancel).call nil end |
#decode(path, sample_rate:, max_decoded_bytes:) ⇒ Object
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 113 def decode(path, sample_rate:, max_decoded_bytes:) worker = Thread.new do decode_owned(path, sample_rate: sample_rate, max_decoded_bytes: max_decoded_bytes) end worker.name = "cohere-ffmpeg-decode" if worker.respond_to?(:name=) worker.report_on_exception = false completed = false result = worker.value completed = true result ensure if defined?(worker) && worker && !completed Thread.handle_interrupt(Exception => :never) do @functions.fetch(:cancel).call if worker.alive? rescue StandardError nil ensure worker.join end end end |
#duration(path) ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 192 def duration(path) duration_slot = Fiddle::Pointer.malloc(Fiddle::SIZEOF_DOUBLE, Fiddle::RUBY_FREE) duration_slot[0, Fiddle::SIZEOF_DOUBLE] = [-1.0].pack("d") = Fiddle::Pointer.malloc(ERROR_CAPACITY, Fiddle::RUBY_FREE) [0, ERROR_CAPACITY] = "\0" * ERROR_CAPACITY status = @functions.fetch(:duration).call( c_string(path.to_s), duration_slot, , ERROR_CAPACITY ) detail = .to_s.force_encoding(Encoding::UTF_8).scrub unless status.zero? raise Interrupt, "Native FFmpeg duration probe was cancelled for #{path}: #{detail}" if status == CANCELLED_STATUS raise TranscriptionRuntimeError, "Cannot inspect #{path} through native FFmpeg: #{detail}" end seconds = duration_slot[0, Fiddle::SIZEOF_DOUBLE].unpack1("d") return nil unless seconds.finite? && seconds >= 0.0 seconds end |
#probe! ⇒ Object
103 104 105 106 107 108 109 110 111 |
# File 'lib/cohere/transcribe/audio/ffmpeg_native.rb', line 103 def probe! = Fiddle::Pointer.malloc(ERROR_CAPACITY, Fiddle::RUBY_FREE) [0, ERROR_CAPACITY] = "\0" * ERROR_CAPACITY status = @functions.fetch(:probe).call(, ERROR_CAPACITY) @diagnostic = .to_s.force_encoding(Encoding::UTF_8).scrub.freeze return self if status.zero? raise TranscriptionRuntimeError, "Native FFmpeg libraries are unavailable: #{@diagnostic}" end |