feat: add transcription backend contracts
This commit is contained in:
1 parent
3b05cb22a0
commit
54e8b42330
9 files changed
+461
No files matched your search
@@ -0,0 +1,80 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::{AppError, AppResult};
|
||||
|
||||
use super::{Transcriber, TranscriptionInput, TranscriptionResult};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CrispAsrConfig {
|
||||
pub sidecar_name: Option<String>,
|
||||
pub model_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CrispAsrTranscriber {
|
||||
config: CrispAsrConfig,
|
||||
}
|
||||
|
||||
impl CrispAsrTranscriber {
|
||||
pub fn new(config: CrispAsrConfig) -> Self {
|
||||
Self { config }
|
||||
}
|
||||
|
||||
pub fn config(&self) -> &CrispAsrConfig {
|
||||
&self.config
|
||||
}
|
||||
}
|
||||
|
||||
impl Transcriber for CrispAsrTranscriber {
|
||||
fn transcribe(&self, input: TranscriptionInput) -> AppResult<TranscriptionResult> {
|
||||
let Some(model_path) = &self.config.model_path else {
|
||||
return Err(AppError::ModelNotInstalled(input.options.model_id));
|
||||
};
|
||||
|
||||
if self.config.sidecar_name.is_none() {
|
||||
return Err(AppError::SidecarNotConfigured);
|
||||
}
|
||||
|
||||
Ok(TranscriptionResult {
|
||||
text: format!(
|
||||
"Transcrição local pendente via CrispASR para {} usando {}.",
|
||||
input.audio_path.display(),
|
||||
model_path.display()
|
||||
),
|
||||
backend: "crispasr".to_string(),
|
||||
model_id: input.options.model_id,
|
||||
detected_language: input.options.language,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::error::AppError;
|
||||
use crate::models::DEFAULT_MODEL_ID;
|
||||
use crate::transcription::{Transcriber, TranscriptionInput, TranscriptionOptions};
|
||||
|
||||
use super::{CrispAsrConfig, CrispAsrTranscriber};
|
||||
|
||||
#[test]
|
||||
fn missing_model_returns_clear_error() {
|
||||
let transcriber = CrispAsrTranscriber::new(CrispAsrConfig {
|
||||
sidecar_name: Some("crispasr".to_string()),
|
||||
model_path: None,
|
||||
});
|
||||
|
||||
let err = transcriber
|
||||
.transcribe(TranscriptionInput {
|
||||
audio_path: PathBuf::from("sample.wav"),
|
||||
options: TranscriptionOptions::default(),
|
||||
})
|
||||
.expect_err("modelo ausente deve falhar");
|
||||
|
||||
assert_eq!(err, AppError::ModelNotInstalled(DEFAULT_MODEL_ID.to_string()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::error::AppResult;
|
||||
use crate::models::DEFAULT_MODEL_ID;
|
||||
|
||||
pub mod crispasr;
|
||||
pub mod openai;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TranscriptionInput {
|
||||
pub audio_path: PathBuf,
|
||||
pub options: TranscriptionOptions,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TranscriptionOptions {
|
||||
pub model_id: String,
|
||||
pub language: Option<String>,
|
||||
pub timestamps: bool,
|
||||
}
|
||||
|
||||
impl Default for TranscriptionOptions {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
model_id: DEFAULT_MODEL_ID.to_string(),
|
||||
language: None,
|
||||
timestamps: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TranscriptionResult {
|
||||
pub text: String,
|
||||
pub backend: String,
|
||||
pub model_id: String,
|
||||
pub detected_language: Option<String>,
|
||||
}
|
||||
|
||||
pub trait Transcriber {
|
||||
fn transcribe(&self, input: TranscriptionInput) -> AppResult<TranscriptionResult>;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OpenAiTranscriptionConfig {
|
||||
pub endpoint: String,
|
||||
pub model: String,
|
||||
pub language: Option<String>,
|
||||
}
|
||||
|
||||
impl Default for OpenAiTranscriptionConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
endpoint: "https://api.openai.com/v1/audio/transcriptions".to_string(),
|
||||
model: "whisper-1".to_string(),
|
||||
language: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user