Add ASR loader module

This commit is contained in:
2026-03-19 01:09:49 +08:00
parent 22fb5dbccd
commit efb9302162

59
src/overlay/asr.rs Normal file
View File

@@ -0,0 +1,59 @@
//! ASR subtitle loader and manager
use anyhow::{Context, Result};
use serde::Deserialize;
use std::path::Path;
#[derive(Debug, Clone, Deserialize)]
pub struct AsrSegment {
pub start: f64,
pub end: f64,
pub text: String,
}
#[derive(Debug, Clone, Deserialize)]
pub struct AsrData {
pub language: Option<String>,
pub language_probability: Option<f64>,
pub segments: Vec<AsrSegment>,
}
#[derive(Debug, Clone)]
pub struct AsrLoader {
data: AsrData,
}
impl AsrLoader {
pub fn load(path: &Path) -> Result<Self> {
let content = std::fs::read_to_string(path)
.with_context(|| format!("Failed to read ASR file: {:?}", path))?;
let data: AsrData = serde_json::from_str(&content)
.with_context(|| "Failed to parse ASR JSON")?;
Ok(Self { data })
}
pub fn get_segment_at(&self, time_ms: f64) -> Option<&AsrSegment> {
let time_sec = time_ms / 1000.0;
self.data.segments.iter().find(|seg| {
time_sec >= seg.start && time_sec < seg.end
})
}
pub fn get_text_at(&self, time_ms: f64) -> Option<String> {
self.get_segment_at(time_ms).map(|seg| seg.text.clone())
}
pub fn get_all_segments(&self) -> &[AsrSegment] {
&self.data.segments
}
pub fn segment_count(&self) -> usize {
self.data.segments.len()
}
pub fn duration(&self) -> f64 {
self.data.segments.last().map(|s| s.end).unwrap_or(0.0)
}
}