rb_define_method(cParams, #param_name, ruby_whisper_params_get_ ## param_name, 0); \
rb_define_method(cParams, #param_name "=", ruby_whisper_params_set_ ## param_name, 1);
-#define RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT 30
+#define RUBY_WHISPER_PARAMS_PARAM_NAMES_COUNT 32
extern VALUE cParams;
static ID id_new_segment_callback_user_data;
static ID id_progress_callback;
static ID id_progress_callback_user_data;
+static ID id_encoder_begin_callback;
+static ID id_encoder_begin_callback_user_data;
static ID id_abort_callback;
static ID id_abort_callback_user_data;
}
}
+static bool encoder_begin_callback(struct whisper_context *ctx, struct whisper_state *state, void *user_data) {
+ const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
+ bool is_aborted = false;
+ VALUE result;
+
+ // Currently, doesn't support state because
+ // those require to resolve GC-related problems.
+ if (!NIL_P(container->callback)) {
+ result = rb_funcall(container->callback, id_call, 3, *container->context, Qnil, container->user_data);
+ if (result == Qfalse) {
+ is_aborted = true;
+ }
+ }
+ const long callbacks_len = RARRAY_LEN(container->callbacks);
+ if (0 == callbacks_len) {
+ return !is_aborted;
+ }
+ for (int j = 0; j < callbacks_len; j++) {
+ VALUE cb = rb_ary_entry(container->callbacks, j);
+ result = rb_funcall(cb, id_call, 0);
+ if (result == Qfalse) {
+ is_aborted = true;
+ }
+ }
+ return !is_aborted;
+}
+
static bool abort_callback(void * user_data) {
const ruby_whisper_callback_container *container = (ruby_whisper_callback_container *)user_data;
if (!NIL_P(container->callback)) {
rwp->params.progress_callback_user_data = rwp->progress_callback_container;
}
+ if (!NIL_P(rwp->encoder_begin_callback_container->callback) || 0 != RARRAY_LEN(rwp->encoder_begin_callback_container->callbacks)) {
+ rwp->encoder_begin_callback_container->context = context;
+ rwp->params.encoder_begin_callback = encoder_begin_callback;
+ rwp->params.encoder_begin_callback_user_data = rwp->encoder_begin_callback_container;
+ }
+
if (!NIL_P(rwp->abort_callback_container->callback) || 0 != RARRAY_LEN(rwp->abort_callback_container->callbacks)) {
rwp->abort_callback_container->context = context;
rwp->params.abort_callback = abort_callback;
{
rb_whisper_callbcack_container_mark(rwp->new_segment_callback_container);
rb_whisper_callbcack_container_mark(rwp->progress_callback_container);
+ rb_whisper_callbcack_container_mark(rwp->encoder_begin_callback_container);
rb_whisper_callbcack_container_mark(rwp->abort_callback_container);
}
rwp->diarize = false;
rwp->new_segment_callback_container = rb_whisper_callback_container_allocate();
rwp->progress_callback_container = rb_whisper_callback_container_allocate();
+ rwp->encoder_begin_callback_container = rb_whisper_callback_container_allocate();
rwp->abort_callback_container = rb_whisper_callback_container_allocate();
return Data_Wrap_Struct(klass, rb_whisper_params_mark, rb_whisper_params_free, rwp);
}
rwp->progress_callback_container->user_data = value;
return value;
}
+
+static VALUE
+ruby_whisper_params_get_encoder_begin_callback(VALUE self)
+{
+ ruby_whisper_params *rwp;
+ Data_Get_Struct(self, ruby_whisper_params, rwp);
+ return rwp->encoder_begin_callback_container->callback;
+}
+
+/*
+ * Sets encoder begin callback, called when the encoder starts.
+ *
+ * params.encoder_begin_callback = ->(context, _, user_data) {
+ * # ...
+ * }
+ *
+ * call-seq:
+ * encoder_begin_callback = callback -> callback
+ */
+static VALUE
+ruby_whisper_params_set_encoder_begin_callback(VALUE self, VALUE value)
+{
+ ruby_whisper_params *rwp;
+ Data_Get_Struct(self, ruby_whisper_params, rwp);
+ rwp->encoder_begin_callback_container->callback = value;
+ return value;
+}
+
+static VALUE
+ruby_whisper_params_get_encoder_begin_callback_user_data(VALUE self)
+{
+ ruby_whisper_params *rwp;
+ Data_Get_Struct(self, ruby_whisper_params, rwp);
+ return rwp->encoder_begin_callback_container->user_data;
+}
+
+/*
+ * Sets user data passed to the last argument of encoder begin callback.
+ *
+ * call-seq:
+ * encoder_begin_callback_user_data = user_data -> use_data
+ */
+static VALUE
+ruby_whisper_params_set_encoder_begin_callback_user_data(VALUE self, VALUE value)
+{
+ ruby_whisper_params *rwp;
+ Data_Get_Struct(self, ruby_whisper_params, rwp);
+ rwp->encoder_begin_callback_container->user_data = value;
+ return value;
+}
+
static VALUE
ruby_whisper_params_get_abort_callback(VALUE self)
{
SET_PARAM_IF_SAME(new_segment_callback_user_data)
SET_PARAM_IF_SAME(progress_callback)
SET_PARAM_IF_SAME(progress_callback_user_data)
+ SET_PARAM_IF_SAME(encoder_begin_callback)
+ SET_PARAM_IF_SAME(encoder_begin_callback_user_data)
SET_PARAM_IF_SAME(abort_callback)
SET_PARAM_IF_SAME(abort_callback_user_data)
}
return Qnil;
}
+/*
+ * Hook called when the encoder starts.
+ *
+ * whisper.on_encoder_begin do
+ * # ...
+ * end
+ *
+ * call-seq:
+ * on_encoder_begin { ... }
+ */
+static VALUE
+ruby_whisper_params_on_encoder_begin(VALUE self)
+{
+ ruby_whisper_params *rws;
+ Data_Get_Struct(self, ruby_whisper_params, rws);
+ const VALUE blk = rb_block_proc();
+ rb_ary_push(rws->encoder_begin_callback_container->callbacks, blk);
+ return Qnil;
+}
+
/*
* Call block to determine whether abort or not. Return +true+ when you want to abort.
*
DEFINE_PARAM(new_segment_callback_user_data, 25)
DEFINE_PARAM(progress_callback, 26)
DEFINE_PARAM(progress_callback_user_data, 27)
- DEFINE_PARAM(abort_callback, 28)
- DEFINE_PARAM(abort_callback_user_data, 29)
+ DEFINE_PARAM(encoder_begin_callback, 28)
+ DEFINE_PARAM(encoder_begin_callback_user_data, 29)
+ DEFINE_PARAM(abort_callback, 30)
+ DEFINE_PARAM(abort_callback_user_data, 31)
rb_define_method(cParams, "on_new_segment", ruby_whisper_params_on_new_segment, 0);
rb_define_method(cParams, "on_progress", ruby_whisper_params_on_progress, 0);
+ rb_define_method(cParams, "on_encoder_begin", ruby_whisper_params_on_encoder_begin, 0);
rb_define_method(cParams, "abort_on", ruby_whisper_params_abort_on, 0);
}
type log_callback = ^(Integer level, String message, Object user_data) -> void
type new_segment_callback = ^(Whisper::Context, void, Integer n_new, Object user_data) -> void
type progress_callback = ^(Whisper::Context, void, Integer progress, Object user_data) -> void
+ type encoder_begin_callback = ^(Whisper::Context, void, Object user_data) -> void
type abort_callback = ^(Whisper::Context, void, Object user_data) -> boolish
LOG_LEVEL_NONE: Integer
?new_segment_callback_user_data: Object,
?progress_callback: progress_callback,
?progress_callback_user_data: Object,
+ ?encoder_begin_callback: encoder_begin_callback,
+ ?encoder_begin_callback_user_data: Object,
?abort_callback: abort_callback,
?abort_callback_user_data: Object
) -> instance
def progress_callback_user_data: () -> Object
+ # Sets encoder begin callback, called when the encoder starts.
+ #
+ def encoder_begin_callback=: (encoder_begin_callback) -> encoder_begin_callback
+
+ def encoder_begin_callback: () -> (encoder_begin_callback | nil)
+
+ # Sets user data passed to the last argument of encoder begin callback.
+ #
+ def encoder_begin_callback_user_data=: (Object) -> Object
+
+ def encoder_begin_callback_user_data: () -> Object
+
# Sets abort callback, called to check if the process should be aborted.
#
# params.abort_callback = ->(user_data) {
#
def on_progress: { (Integer progress) -> void } -> void
+ # Hook called on encoder starts.
+ #
+ def on_encoder_begin: { () -> void } -> void
+
# Call block to determine whether abort or not. Return +true+ when you want to abort.
#
# params.abort_on do
assert_equal 100, last
end
+ def test_encoder_begin_callback
+ i = 0
+ @params.encoder_begin_callback = ->(context, state, user_data) {
+ i += 1
+ }
+ @whisper.transcribe(@audio, @params)
+ assert i > 0
+ end
+
+ def test_encoder_begin_callback_abort
+ logs = []
+ Whisper.log_set -> (level, buffer, user_data) {
+ logs << buffer if level == Whisper::LOG_LEVEL_ERROR
+ }, logs
+ @params.encoder_begin_callback = ->(context, state, user_data) {
+ return false
+ }
+ @whisper.transcribe(@audio, @params)
+ assert_match(/encoder_begin_callback returned false - aborting/, logs.join)
+ Whisper.log_set ->(level, buffer, user_data) {}, nil
+ end
+
+ def test_encoder_begin_callback_user_data
+ udata = Object.new
+ @params.encoder_begin_callback_user_data = udata
+ yielded = nil
+ @params.encoder_begin_callback = ->(context, state, user_data) {
+ yielded = user_data
+ }
+ @whisper.transcribe(@audio, @params)
+ assert_same udata, yielded
+ end
+
+ def test_on_encoder_begin
+ i = 0
+ @params.on_encoder_begin do
+ i += 1
+ end
+ @whisper.transcribe(@audio, @params)
+ assert i > 0
+ end
+
def test_abort_callback
i = 0
@params.abort_callback = ->(user_data) {