diff --git a/bindings/ruby/README.md b/bindings/ruby/README.md index 7f6b7d92c09..d5ac2336af0 100644 --- a/bindings/ruby/README.md +++ b/bindings/ruby/README.md @@ -117,7 +117,7 @@ Whisper::Params.new( threshold: 1.0, # defaults to 0.5 min_speech_duration_ms: 500, # defaults to 250 min_silence_duration_ms: 200, # defaults to 100 - max_speech_duration_s: 30000, # default is FLT_MAX, + max_speech_duration_s: 30000.0, # default is FLT_MAX, speech_pad_ms: 50, # defaults to 30 samples_overlap: 0.5 # defaults to 0.1 ), @@ -176,7 +176,7 @@ See whisper.cpp's [README](https://github.com/ggml-org/whisper.cpp/blob/master/R Boolean options: * `-DGGML_BLAS=1` -> `--enable-ggml-blas` -* `-DWHISER_COREML=OFF` -> `--disable-whisper-coreml` +* `-DWHISPER_COREML=OFF` -> `--disable-whisper-coreml` Argument options: @@ -184,7 +184,7 @@ Argument options: Combination: -* `-DGGML_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="86"` -> `--enable-ggml-cuda --cmake_cuda-architectures="86"` +* `-DGGML_CUDA=1 -DCMAKE_CUDA_ARCHITECTURES="86"` -> `--enable-ggml-cuda --cmake-cuda-architectures="86"` For boolean options like `GGML_CUDA`, the README says `-DGGML_CUDA=1`. You need strip `-D`, prepend `--enable-` for `1` or `ON` (`--disable-` for `0` or `OFF`) and make it kebab-case: `--enable-ggml-cuda`. For options which require arguments like `CMAKE_CUDA_ARCHITECTURES`, the README says `-DCMAKE_CUDA_ARCHITECTURES="86"`. You need strip `-D`, prepend `--`, make it kebab-case, append `=` and append argument: `--cmake-cuda-architectures="86"`. @@ -478,13 +478,14 @@ Development % cd whisper.cpp/bindings/ruby % rake test -First call of `rake test` builds an extension and downloads a model for testing. After that, you add tests in `tests` directory and modify `ext/ruby_whisper.cpp`. +First call of `rake test` builds an extension and downloads a model for testing. After that, you add tests in `test` directory and modify `ext/*.{h,c,cpp}`. If something seems wrong on build, running `rake clean` solves some cases. ### Need help ### * Windows support +* Check of compilation with various hardware * Refinement of C/C++ code, especially memory management License diff --git a/bindings/ruby/ext/options.rb b/bindings/ruby/ext/options.rb index e723af9fd9a..c097ccb8ad6 100644 --- a/bindings/ruby/ext/options.rb +++ b/bindings/ruby/ext/options.rb @@ -105,7 +105,7 @@ def write_cache_file FileUtils.mkpath File.dirname(cache_path) File.open cache_path, "w" do |file| @options.reject {|name, (type, value)| value.nil?}.each do |name, (type, value)| - line = "set(CACHE{%s} TYPE %s FORCE VALUE %s)" % { + line = 'set(%s %s CACHE %s "" FORCE)' %{ name:, type:, value: value == true ? "ON" : value == false ? "OFF" : escape_cmake(value) diff --git a/bindings/ruby/ext/ruby_whisper.c b/bindings/ruby/ext/ruby_whisper.c index 7941b1a99dd..bd852a86df7 100644 --- a/bindings/ruby/ext/ruby_whisper.c +++ b/bindings/ruby/ext/ruby_whisper.c @@ -133,7 +133,6 @@ void Init_whisper() { id_coreml_compiled_models = rb_intern("coreml_compiled_models"); id_cache = rb_intern("cache"); id_n_processors = rb_intern("n_processors"); - id_extended = rb_intern("extended"); id_start_log_callback_thread = rb_intern("start_log_callback_thread"); id_log_callback_thread = rb_intern("@log_callback_thread"); id_alive_p = rb_intern("alive?"); diff --git a/bindings/ruby/ext/ruby_whisper.h b/bindings/ruby/ext/ruby_whisper.h index 10e90674953..b977703eeee 100644 --- a/bindings/ruby/ext/ruby_whisper.h +++ b/bindings/ruby/ext/ruby_whisper.h @@ -110,6 +110,13 @@ typedef struct { int n_samples; } ruby_whisper_full_args; +typedef struct segments_from_samples_args { + VALUE *context; + VALUE *params; + float *samples; + int n_samples; +} segments_from_samples_args; + typedef struct ruby_whisper_full_parallel_args { VALUE *context; VALUE *params; @@ -149,7 +156,6 @@ typedef struct { VALUE context; } ruby_whisper_parakeet_model; -extern ID id_extended; extern ID id_log_callback_thread; extern ID id_start_log_callback_thread; extern ID id_alive_p; diff --git a/bindings/ruby/ext/ruby_whisper_context.c b/bindings/ruby/ext/ruby_whisper_context.c index 9e5fc33e726..0210ac8a98b 100644 --- a/bindings/ruby/ext/ruby_whisper_context.c +++ b/bindings/ruby/ext/ruby_whisper_context.c @@ -349,7 +349,11 @@ fill_samples(VALUE rb_args) if (RB_TYPE_P(*args->src, T_ARRAY)) { for (int i = 0; i < args->n_samples; i++) { - args->dest[i] = RFLOAT_VALUE(rb_ary_entry(*args->src, i)); + VALUE sample = rb_ary_entry(*args->src, i); + if (!RB_FLOAT_TYPE_P(sample)) { + sample = rb_to_float(sample); + } + args->dest[i] = RFLOAT_VALUE(sample); } } else { // TODO: use rb_block_call @@ -357,6 +361,9 @@ fill_samples(VALUE rb_args) for (int i = 0; i < args->n_samples; i++) { // TODO: check if iter is exhausted and raise ArgumentError appropriately VALUE sample = rb_funcall(iter, id_next, 0); + if (!RB_FLOAT_TYPE_P(sample)) { + sample = rb_to_float(sample); + } args->dest[i] = RFLOAT_VALUE(sample); } } @@ -745,6 +752,45 @@ ruby_whisper_full_get_segment_no_speech_prob(VALUE self, VALUE i_segment) return DBL2NUM(no_speech_prob); } +static VALUE +ruby_whisper_full_n_vad_segments(VALUE self) +{ + ruby_whisper *rw; + GetContext(self, rw); + + return INT2NUM(whisper_full_n_vad_segments(rw->context)); +} + +static int +ruby_whisper_full_check_vad_segment_index(const ruby_whisper *rw, const VALUE i_segment) +{ + const int c_i_segment = NUM2INT(i_segment); + if (c_i_segment < 0 || c_i_segment >= whisper_full_n_vad_segments(rw->context)) { + rb_raise(rb_eIndexError, "segment index %d out of range", c_i_segment); + } + return c_i_segment; +} + +static VALUE +ruby_whisper_full_get_vad_segment_t0(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_vad_segment_index(rw, i_segment); + + return LONG2NUM(whisper_full_get_vad_segment_t0(rw->context, c_i_segment)); +} + +static VALUE +ruby_whisper_full_get_vad_segment_t1(VALUE self, VALUE i_segment) +{ + ruby_whisper *rw; + GetContext(self, rw); + const int c_i_segment = ruby_whisper_full_check_vad_segment_index(rw, i_segment); + + return LONG2NUM(whisper_full_get_vad_segment_t1(rw->context, c_i_segment)); +} + // High level API static VALUE @@ -830,6 +876,9 @@ init_ruby_whisper_context(VALUE *mWhisper) rb_define_method(cContext, "full_get_segment_speaker_turn_next", ruby_whisper_full_get_segment_speaker_turn_next, 1); rb_define_method(cContext, "full_get_segment_text", ruby_whisper_full_get_segment_text, 1); rb_define_method(cContext, "full_get_segment_no_speech_prob", ruby_whisper_full_get_segment_no_speech_prob, 1); + rb_define_method(cContext, "full_n_vad_segments", ruby_whisper_full_n_vad_segments, 0); + rb_define_method(cContext, "full_get_vad_segment_t0", ruby_whisper_full_get_vad_segment_t0, 1); + rb_define_method(cContext, "full_get_vad_segment_t1", ruby_whisper_full_get_vad_segment_t1, 1); rb_define_method(cContext, "full", ruby_whisper_full, -1); rb_define_method(cContext, "full_parallel", ruby_whisper_full_parallel, -1); diff --git a/bindings/ruby/ext/ruby_whisper_log_settable.h b/bindings/ruby/ext/ruby_whisper_log_settable.h index b98fbac826b..04f9877b70a 100644 --- a/bindings/ruby/ext/ruby_whisper_log_settable.h +++ b/bindings/ruby/ext/ruby_whisper_log_settable.h @@ -41,7 +41,6 @@ rb_define_singleton_method(mod, "drain_logs", ruby_whisper_##log_queue##_s_drain_logs, 0); \ rb_define_singleton_method(mod, "log_set", ruby_whisper_##log_queue##_s_log_set, 2); \ rb_set_end_proc(ruby_whisper_##log_queue##_end_proc, Qnil); \ - rb_extend_object(mod, mLogSettable); \ - rb_funcall(mLogSettable, id_extended, 1, mod); + rb_extend_object(mod, mLogSettable); #endif diff --git a/bindings/ruby/ext/ruby_whisper_params.c b/bindings/ruby/ext/ruby_whisper_params.c index f38e9bde3ea..be874d51a5f 100644 --- a/bindings/ruby/ext/ruby_whisper_params.c +++ b/bindings/ruby/ext/ruby_whisper_params.c @@ -446,7 +446,7 @@ ruby_whisper_params_allocate(VALUE klass) rwp->params.vad_model_path = ruby_strdup(rwp->params.vad_model_path); } rwp->diarize = false; - rwp->vad_params = TypedData_Wrap_Struct(cVADParams, &ruby_whisper_vad_params_type, (void *)&rwp->params.vad_params); + rwp->vad_params = rb_class_new_instance(0, NULL, cVADParams); rwp->new_segment_callback_container = ruby_whisper_callback_container_allocate(); rwp->progress_callback_container = ruby_whisper_callback_container_allocate(); rwp->encoder_begin_callback_container = ruby_whisper_callback_container_allocate(); @@ -918,7 +918,7 @@ ruby_whisper_params_set_temperature(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.temperature = RFLOAT_VALUE(value); + rwp->params.temperature = NUM2DBL(value); return value; } /* @@ -943,7 +943,7 @@ ruby_whisper_params_set_max_initial_ts(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.max_initial_ts = RFLOAT_VALUE(value); + rwp->params.max_initial_ts = NUM2DBL(value); return value; } /* @@ -966,7 +966,7 @@ ruby_whisper_params_set_length_penalty(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.length_penalty = RFLOAT_VALUE(value); + rwp->params.length_penalty = NUM2DBL(value); return value; } /* @@ -989,7 +989,7 @@ ruby_whisper_params_set_temperature_inc(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.temperature_inc = RFLOAT_VALUE(value); + rwp->params.temperature_inc = NUM2DBL(value); return value; } /* @@ -1014,7 +1014,7 @@ ruby_whisper_params_set_entropy_thold(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.entropy_thold = RFLOAT_VALUE(value); + rwp->params.entropy_thold = NUM2DBL(value); return value; } /* @@ -1037,7 +1037,7 @@ ruby_whisper_params_set_logprob_thold(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.logprob_thold = RFLOAT_VALUE(value); + rwp->params.logprob_thold = NUM2DBL(value); return value; } /* @@ -1060,7 +1060,7 @@ ruby_whisper_params_set_no_speech_thold(VALUE self, VALUE value) { ruby_whisper_params *rwp; TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); - rwp->params.no_speech_thold = RFLOAT_VALUE(value); + rwp->params.no_speech_thold = NUM2DBL(value); return value; } static VALUE @@ -1307,6 +1307,7 @@ static VALUE ruby_whisper_params_set_vad_params(VALUE self, VALUE value) { ruby_whisper_params *rwp; + rb_check_typeddata(value, &ruby_whisper_vad_params_type); TypedData_Get_Struct(self, ruby_whisper_params, &ruby_whisper_params_type, rwp); rwp->vad_params = value; return value; diff --git a/bindings/ruby/ext/ruby_whisper_transcribe.cpp b/bindings/ruby/ext/ruby_whisper_transcribe.cpp index 73f606ca476..699f9c6a0ae 100644 --- a/bindings/ruby/ext/ruby_whisper_transcribe.cpp +++ b/bindings/ruby/ext/ruby_whisper_transcribe.cpp @@ -15,28 +15,9 @@ extern ID id_call; extern ID id_to_path; extern ID transcribe_option_names[1]; -extern void prepare_transcription(ruby_whisper_params * rwp, VALUE * self, int n_processors); extern VALUE full_body(VALUE rb_args); extern VALUE full_parallel_body(VALUE rb_args); -typedef struct{ - struct whisper_context *context; - struct whisper_full_params *params; - float *samples; - size_t n_samples; - int n_processors; - int result; -} transcribe_without_gvl_args; - -static void* -transcribe_without_gvl(void *rb_args) -{ - transcribe_without_gvl_args *args = (transcribe_without_gvl_args *)rb_args; - args->result = whisper_full_parallel(args->context, *args->params, args->samples, args->n_samples, args->n_processors); - - return NULL; -} - /* * transcribe a single file * can emit to a block results diff --git a/bindings/ruby/ext/ruby_whisper_vad_context.c b/bindings/ruby/ext/ruby_whisper_vad_context.c index 97c9736b6f4..32320092472 100644 --- a/bindings/ruby/ext/ruby_whisper_vad_context.c +++ b/bindings/ruby/ext/ruby_whisper_vad_context.c @@ -12,13 +12,6 @@ extern VALUE release_samples(VALUE parsed); extern VALUE ruby_whisper_vad_segments_s_init(struct whisper_vad_segments *segments); -typedef struct segments_from_samples_args { - VALUE *context; - VALUE *params; - float *samples; - int n_samples; -} segments_from_samples_args; - static size_t ruby_whisper_vad_context_memsize(const void *p) { @@ -77,7 +70,24 @@ ruby_whisper_vad_context_initialize(VALUE self, VALUE model_path) return Qnil; } -static VALUE +typedef struct { + struct whisper_vad_context *context; + struct whisper_vad_params *params; + float *samples; + int n_samples; + struct whisper_vad_segments *result; +} segments_from_samples_without_gvl_args; + +static void* +segments_from_samples_without_gvl(void *rb_args) +{ + segments_from_samples_without_gvl_args *args = (segments_from_samples_without_gvl_args *)rb_args; + args->result = whisper_vad_segments_from_samples(args->context, *args->params, args->samples, args->n_samples); + + return NULL; +} + +VALUE segments_from_samples_body(VALUE rb_args) { segments_from_samples_args *args = (segments_from_samples_args *)rb_args; @@ -87,9 +97,19 @@ segments_from_samples_body(VALUE rb_args) GetVADContext(*args->context, rwvc); GetVADParams(*args->params, rwvp); - struct whisper_vad_segments *segments = whisper_vad_segments_from_samples(rwvc->context, rwvp->params, args->samples, args->n_samples); + segments_from_samples_without_gvl_args segments_from_samples_without_gvl_args = { + rwvc->context, + &rwvp->params, + args->samples, + args->n_samples, + NULL + }; + rb_thread_call_without_gvl(segments_from_samples_without_gvl, (void *)&segments_from_samples_without_gvl_args, NULL, NULL); + if (!segments_from_samples_without_gvl_args.result) { + rb_raise(rb_eRuntimeError, "Failed to process audio"); + } - return ruby_whisper_vad_segments_s_init(segments); + return ruby_whisper_vad_segments_s_init(segments_from_samples_without_gvl_args.result); } static VALUE diff --git a/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp b/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp index 802b0222dbd..862da811aa9 100644 --- a/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp +++ b/bindings/ruby/ext/ruby_whisper_vad_context_detect.cpp @@ -16,18 +16,16 @@ extern const rb_data_type_t ruby_whisper_vad_params_type; extern const rb_data_type_t ruby_whisper_vad_segments_type; extern VALUE ruby_whisper_vad_segments_s_init(struct whisper_vad_segments *segments); +extern VALUE segments_from_samples_body(VALUE rb_args); VALUE ruby_whisper_vad_detect(VALUE self, VALUE file_path, VALUE params) { ruby_whisper_vad_context *rwvc; - ruby_whisper_vad_params *rwvp; std::string cpp_file_path; std::vector pcmf32; std::vector> pcmf32s; - whisper_vad_segments *segments; GetVADContext(self, rwvc); - TypedData_Get_Struct(params, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); if (rb_respond_to(file_path, id_to_path)) { file_path = rb_funcall(file_path, id_to_path, 0); @@ -38,12 +36,13 @@ ruby_whisper_vad_detect(VALUE self, VALUE file_path, VALUE params) { rb_raise(rb_eRuntimeError, "Failed to open '%s' as WAV file\n", cpp_file_path.c_str()); } - segments = whisper_vad_segments_from_samples(rwvc->context, rwvp->params, pcmf32.data(), pcmf32.size()); - if (segments == nullptr) { - rb_raise(rb_eRuntimeError, "Failed to process audio\n"); - } - - return ruby_whisper_vad_segments_s_init(segments); + segments_from_samples_args args = { + &self, + ¶ms, + pcmf32.data(), + (int)pcmf32.size(), + }; + return segments_from_samples_body((VALUE)&args); } #ifdef __cplusplus diff --git a/bindings/ruby/ext/ruby_whisper_vad_params.c b/bindings/ruby/ext/ruby_whisper_vad_params.c index 28256650e32..edcc25d763e 100644 --- a/bindings/ruby/ext/ruby_whisper_vad_params.c +++ b/bindings/ruby/ext/ruby_whisper_vad_params.c @@ -31,7 +31,7 @@ static ID id_samples_overlap; const rb_data_type_t ruby_whisper_vad_params_type = { "ruby_whisper_vad_params", - {0, 0, ruby_whisper_vad_params_memsize,}, + {0, RUBY_DEFAULT_FREE, ruby_whisper_vad_params_memsize,}, 0, 0, 0 }; @@ -56,7 +56,7 @@ ruby_whisper_vad_params_set_threshold(VALUE self, VALUE value) { ruby_whisper_vad_params *rwvp; TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); - rwvp->params.threshold = RFLOAT_VALUE(value); + rwvp->params.threshold = NUM2DBL(value); return value; } @@ -125,7 +125,7 @@ ruby_whisper_vad_params_set_max_speech_duration_s(VALUE self, VALUE value) { ruby_whisper_vad_params *rwvp; TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); - rwvp->params.max_speech_duration_s = RFLOAT_VALUE(value); + rwvp->params.max_speech_duration_s = NUM2DBL(value); return value; } @@ -171,7 +171,7 @@ ruby_whisper_vad_params_set_samples_overlap(VALUE self, VALUE value) { ruby_whisper_vad_params *rwvp; TypedData_Get_Struct(self, ruby_whisper_vad_params, &ruby_whisper_vad_params_type, rwvp); - rwvp->params.samples_overlap = RFLOAT_VALUE(value); + rwvp->params.samples_overlap = NUM2DBL(value); return value; } diff --git a/bindings/ruby/ext/ruby_whisper_vad_segment.c b/bindings/ruby/ext/ruby_whisper_vad_segment.c index 84a007bb725..0db6db6e253 100644 --- a/bindings/ruby/ext/ruby_whisper_vad_segment.c +++ b/bindings/ruby/ext/ruby_whisper_vad_segment.c @@ -68,7 +68,7 @@ ruby_whisper_vad_segment_get_start_time(VALUE self) TypedData_Get_Struct(self, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); TypedData_Get_Struct(rwvs->segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); t0 = whisper_vad_segments_get_segment_t0(rwvss->segments, rwvs->index); - return DBL2NUM(t0 * 10); + return LONG2NUM(t0 * 10); } static VALUE @@ -81,7 +81,7 @@ ruby_whisper_vad_segment_get_end_time(VALUE self) TypedData_Get_Struct(self, ruby_whisper_vad_segment, &ruby_whisper_vad_segment_type, rwvs); TypedData_Get_Struct(rwvs->segments, ruby_whisper_vad_segments, &ruby_whisper_vad_segments_type, rwvss); t1 = whisper_vad_segments_get_segment_t1(rwvss->segments, rwvs->index); - return DBL2NUM(t1 * 10); + return LONG2NUM(t1 * 10); } static VALUE diff --git a/bindings/ruby/lib/whisper/log_settable.rb b/bindings/ruby/lib/whisper/log_settable.rb index 2f8218d26ee..57378a4b226 100644 --- a/bindings/ruby/lib/whisper/log_settable.rb +++ b/bindings/ruby/lib/whisper/log_settable.rb @@ -1,13 +1,5 @@ -require "mutex_m" - module Whisper module LogSettable - class << self - def extended(base) - base.extend Mutex_m - end - end - private def start_log_callback_thread @@ -32,5 +24,10 @@ def start_log_callback_thread end } end + + def synchronize(&block) + @mutex ||= Thread::Mutex.new + @mutex.synchronize &block + end end end diff --git a/bindings/ruby/lib/whisper/model/uri.rb b/bindings/ruby/lib/whisper/model/uri.rb index ef92eb901c4..58db3766dad 100644 --- a/bindings/ruby/lib/whisper/model/uri.rb +++ b/bindings/ruby/lib/whisper/model/uri.rb @@ -44,7 +44,6 @@ def cache return path if cache_path.exist? headers = {} - headers["if-modified-since"] = path.mtime.httpdate if path.exist? request @uri, headers path end @@ -54,17 +53,11 @@ def request(uri, headers) request = Net::HTTP::Get.new(uri, headers) http.request request do |response| case response - when Net::HTTPNotModified - # noop when Net::HTTPOK - return if !response.key?("last-modified") && cache_path.exist? - download response when Net::HTTPRedirection request URI(response["location"]), headers else - return if headers.key?("if-modified-since") # Use cache file - raise "#{response.code} #{response.message}\n#{response.body}" end end diff --git a/bindings/ruby/sig/whisper.rbs b/bindings/ruby/sig/whisper.rbs index c12e1fe55e5..f2ebf6185fd 100644 --- a/bindings/ruby/sig/whisper.rbs +++ b/bindings/ruby/sig/whisper.rbs @@ -131,6 +131,12 @@ module Whisper def full_get_segment_no_speech_prob: (Integer) -> Float + def full_n_vad_segments: () -> Integer + + def full_get_vad_segment_t0: (Integer) -> Integer + + def full_get_vad_segment_t1: (Integer) -> Integer + # Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text # Not thread safe for same context # Uses the specified decoding strategy to obtain the text. diff --git a/bindings/ruby/test/test_vad.rb b/bindings/ruby/test/test_vad.rb index 3b0aedd061a..8d3d94d9a49 100644 --- a/bindings/ruby/test/test_vad.rb +++ b/bindings/ruby/test/test_vad.rb @@ -16,4 +16,13 @@ def test_transcribe assert_match(/ask not what your country can do for you[,.] ask what you can do for your country/i, text) end end + + def test_vad_segments_api + @whisper.transcribe TestBase::AUDIO, @params + + assert_equal 4, @whisper.full_n_vad_segments + @whisper.full_n_vad_segments.times do |i| + assert @whisper.full_get_vad_segment_t0(i) < @whisper.full_get_vad_segment_t1(i) + end + end end diff --git a/bindings/ruby/test/test_vad_context.rb b/bindings/ruby/test/test_vad_context.rb index b4558d34faf..77772467505 100644 --- a/bindings/ruby/test/test_vad_context.rb +++ b/bindings/ruby/test/test_vad_context.rb @@ -44,8 +44,8 @@ def assert_segments(segments) assert_instance_of Enumerator, segments.each segment = segments.each.first - assert_instance_of Float, segment.start_time - assert_instance_of Float, segment.end_time + assert_instance_of Integer, segment.start_time + assert_instance_of Integer, segment.end_time segment => {start_time:, end_time:} assert_equal segment.start_time, start_time diff --git a/bindings/ruby/whispercpp.gemspec b/bindings/ruby/whispercpp.gemspec index 301ecfcc13d..20068aa162c 100644 --- a/bindings/ruby/whispercpp.gemspec +++ b/bindings/ruby/whispercpp.gemspec @@ -3,7 +3,7 @@ require_relative "extsources" Gem::Specification.new do |s| s.name = "whispercpp" s.authors = ["Georgi Gerganov", "Todd A. Fisher"] - s.version = '1.3.7' + s.version = '1.3.8' s.description = %q{High-performance inference of OpenAI's Whisper automatic speech recognition (ASR) model via Ruby} s.email = 'todd.fisher@gmail.com' s.extra_rdoc_files = ['LICENSE', 'README.md']