feat(voice): add reusable transcript records
This commit is contained in:
@@ -93,6 +93,7 @@ struct SegmentRow {
|
||||
sequence: i32,
|
||||
duration_ms: i32,
|
||||
status: String,
|
||||
transcript: Option<String>,
|
||||
error_message: Option<String>,
|
||||
}
|
||||
|
||||
@@ -141,6 +142,7 @@ struct LessonSummaryResponse {
|
||||
duration_ms: i32,
|
||||
applied_directly: bool,
|
||||
included_in_generation: bool,
|
||||
transcript: String,
|
||||
segments: Vec<AudioSegmentResponse>,
|
||||
started_at: DateTime<Utc>,
|
||||
ended_at: Option<DateTime<Utc>>,
|
||||
@@ -614,8 +616,8 @@ async fn finish_lesson_session(
|
||||
post,
|
||||
path = "/api/v1/feedback-lessons/{lesson_id}/mark-applied",
|
||||
tag = "语音反馈",
|
||||
summary = "标记短录音已加入反馈",
|
||||
description = "短录音文字直接加入反馈内容后,标记该节课无需再次汇总。",
|
||||
summary = "标记录音已加入反馈",
|
||||
description = "教师将该节转写手动加入反馈内容后,标记该节课无需再次汇总。",
|
||||
params(
|
||||
("Authorization" = String, Header, description = "Bearer 会话令牌", example = "Bearer <access-token>"),
|
||||
("lesson_id" = Uuid, Path, description = "课堂录音 ID")
|
||||
@@ -967,7 +969,8 @@ async fn load_session_response(
|
||||
.fetch_all(pool)
|
||||
.await?;
|
||||
let segments = sqlx::query_as::<_, SegmentRow>(
|
||||
"SELECT s.id, s.lesson_session_id, s.sequence, s.duration_ms, s.status, s.error_message \
|
||||
"SELECT s.id, s.lesson_session_id, s.sequence, s.duration_ms, s.status, \
|
||||
s.transcript, s.error_message \
|
||||
FROM audio_segments s JOIN lesson_sessions l ON l.id = s.lesson_session_id \
|
||||
WHERE l.feedback_session_id = $1 ORDER BY l.sequence, s.sequence",
|
||||
)
|
||||
@@ -994,7 +997,16 @@ async fn load_session_response(
|
||||
lesson.status == "ready" && !lesson.applied_directly && !lesson.included_in_generation
|
||||
});
|
||||
let mut segments_by_lesson: HashMap<Uuid, Vec<AudioSegmentResponse>> = HashMap::new();
|
||||
let mut transcripts_by_lesson: HashMap<Uuid, Vec<String>> = HashMap::new();
|
||||
for segment in segments {
|
||||
if segment.status == "ready" {
|
||||
if let Some(transcript) = segment.transcript.as_deref() {
|
||||
transcripts_by_lesson
|
||||
.entry(segment.lesson_session_id)
|
||||
.or_default()
|
||||
.push(transcript.to_owned());
|
||||
}
|
||||
}
|
||||
segments_by_lesson
|
||||
.entry(segment.lesson_session_id)
|
||||
.or_default()
|
||||
@@ -1016,6 +1028,10 @@ async fn load_session_response(
|
||||
duration_ms: lesson.duration_ms,
|
||||
applied_directly: lesson.applied_directly,
|
||||
included_in_generation: lesson.included_in_generation,
|
||||
transcript: transcripts_by_lesson
|
||||
.remove(&lesson.id)
|
||||
.unwrap_or_default()
|
||||
.join("\n"),
|
||||
segments: segments_by_lesson.remove(&lesson.id).unwrap_or_default(),
|
||||
started_at: lesson.started_at,
|
||||
ended_at: lesson.ended_at,
|
||||
|
||||
@@ -968,6 +968,10 @@ mod tests {
|
||||
assert!(document["info"].get("license").is_none());
|
||||
assert!(document["components"]["schemas"]["ProfileInput"]["example"].is_object());
|
||||
assert!(document["components"]["schemas"]["ProfileDefaultsInput"]["example"].is_object());
|
||||
assert!(
|
||||
document["components"]["schemas"]["LessonSummaryResponse"]["properties"]["transcript"]
|
||||
.is_object()
|
||||
);
|
||||
assert!(
|
||||
document["components"]["schemas"]["FeedbackRecordInput"]["example"]["profile_id"]
|
||||
.is_null()
|
||||
|
||||
Reference in New Issue
Block a user