0

I am trying to create a wrapper around the OpenAI Whisper Rust library whisper-rs for my usecase. I have created a Whisper struct which holds the context, state, parameters and configs. I want these to work in a different worker thread (future implementation). I want the data to have a static lifetime.

use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperState};
use std::sync::{Arc, Mutex,};
use once_cell::sync::OnceCell;

pub struct WhisperCore<'a> {
    ctx: Option<Arc<WhisperContext>>,
    state: Option<Arc<WhisperState<'a>>>,
}

impl WhisperCore<'_> {
    pub fn new() -> Self {
        WhisperCore
            {
                ctx: None,
                state: None,
            }
    } 
}

pub struct Whisper {
    inner: Arc<Mutex<WhisperCore<'static>>>,
}

impl Whisper{
    pub fn get_instance() -> Arc<Mutex<WhisperCore<'static>>> {
        static INSTANCE: OnceCell<Arc<Mutex<WhisperCore<'static>>>> = OnceCell::new();
        let singleton = INSTANCE.get_or_init(|| {
            Arc::new(Mutex::new(WhisperCore::new()))
        });
        Arc::clone(singleton)
    }
    pub fn set_whisper_ctx(&self, path: Option<&'static str>){
        let mut whisper_entity = self.inner.lock().unwrap();
        match path {
            Some(value) => {
                let ctx = Arc::new(WhisperContext::new(value).unwrap());
                whisper_entity.ctx = Some(ctx);
            },
            None => {
                println!("Empty model path");
            }
        }
    }
    pub fn set_whisper_state(&self){
        let mut whisper_entity = self.inner.lock().unwrap();
        if let Some(ctx) = whisper_entity.ctx.clone() {
            let state = Arc::new(ctx.create_state().expect("failed to create key"));
            whisper_entity.state = Some(state);
        } else {
            println!("hiheiheih")
        }   
    }
    pub fn start(&self) {
        self.set_whisper_ctx(Some("/path/model"));
        self.set_whisper_state();
    }
}

I am getting this error when I try to set_whisper_state, the error is happening on this line whisper_entity.state = Some(state). I also tried various steps such as cloning the ctx before using it to get the state in set_whisper_state function. Please help me with this issue.

error[E0597]: `ctx` does not live long enough
   --> src\speech_to_text\whisper.rs:166:34
    |
165 |         if let Some(ctx) = whisper_entity.ctx.clone() {
    |                     --- binding `ctx` declared here
166 |             let state = Arc::new(ctx.create_state().expect("failed to create key"));
    |                                  ^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
167 |             whisper_entity.state = Some(state);
168 |         } else {
    |         - `ctx` dropped here while still borrowed
...
173 |     }
    |     - borrow might be used here, when `whisper_entity` is dropped and runs the `Drop` code for type `MutexGuard`
    |
    = note: values in a scope are dropped in the opposite order they are defined
  • Can you please remove all irrelevant bits and provide a [**minimal** reproduceible example](/help/minimal-reproducible-example)? – cafce25 Jul 30 '23 at 14:22
  • I have removed all irrelevant parts, and have only those code which is necessary to recreate the issue. – Sushant S Samuel Jul 30 '23 at 14:34
  • Seems to be a case of [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/questions/32300132/why-cant-i-store-a-value-and-a-reference-to-that-value-in-the-same-struct) because though you store the context in an `Arc` `create_state` doesn't know or use that fact. – cafce25 Jul 30 '23 at 14:53
  • That is why I moved to use Arc to store the context, in the link provided it also mentioned using reference counting along with the other libraries. At the start of the fix it has mentioned not to add these data in the same struct. So should I also try moving the ctx out of Whisper Core into the main Whisper struct ? – Sushant S Samuel Jul 30 '23 at 15:17
  • Well for reference counting to work `create_state` would have to also use it, but it uses a plain reference. You can probably use one of the self reference crates in the answers or yes, separate the context and the state. But putting ctx into `Whisper` where you also store the state won't help. If going down that route they can't be (not even indirectly) in the same struct. – cafce25 Jul 30 '23 at 15:19

0 Answers0