Skip to main content

whisper_macos_cli/
output.rs

1use serde::Serialize;
2use serde_json::json;
3use std::io::{self, BufWriter, Write};
4
5pub const SCHEMA_VERSION: &str = env!("CARGO_PKG_VERSION");
6
7#[derive(Serialize)]
8pub struct TranscriptionResult {
9    pub schema_version: &'static str,
10    pub correlation_id: String,
11    pub file: String,
12    pub language: String,
13    pub language_source: String,
14    pub model: String,
15    pub duration_seconds: f64,
16    pub text: String,
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub segments: Option<Vec<Segment>>,
19    pub vad_chunks: usize,
20    pub processing_time_ms: u128,
21}
22
23#[derive(Serialize)]
24pub struct Segment {
25    pub start: f64,
26    pub end: f64,
27    pub text: String,
28}
29
30#[derive(Serialize)]
31pub struct ErrorOutput {
32    pub schema_version: &'static str,
33    pub error: bool,
34    pub code: u8,
35    pub message: String,
36    pub category: String,
37    pub retryable: bool,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub retry_after_ms: Option<u64>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub hint: Option<String>,
42    pub docs_url: &'static str,
43    pub correlation_id: String,
44}
45
46pub fn write_json(result: &TranscriptionResult) -> io::Result<()> {
47    let mut stdout = BufWriter::new(io::stdout().lock());
48    serde_json::to_writer(&mut stdout, result)?;
49    stdout.write_all(b"\n")?;
50    stdout.flush()
51}
52
53pub fn write_ndjson(result: &TranscriptionResult) -> io::Result<()> {
54    let mut stdout = BufWriter::new(io::stdout().lock());
55    serde_json::to_writer(&mut stdout, result)?;
56    stdout.write_all(b"\n")?;
57    stdout.flush()
58}
59
60pub fn write_stdout_line(text: &str) -> io::Result<()> {
61    let mut stdout = BufWriter::new(io::stdout().lock());
62    stdout.write_all(text.as_bytes())?;
63    stdout.write_all(b"\n")?;
64    stdout.flush()
65}
66
67pub fn write_schema(schema: &serde_json::Value) -> io::Result<()> {
68    let mut stdout = BufWriter::new(io::stdout().lock());
69    serde_json::to_writer_pretty(&mut stdout, schema)?;
70    stdout.write_all(b"\n")?;
71    stdout.flush()
72}
73
74pub fn write_error(err: &crate::error::Error, correlation_id: &str) -> io::Result<()> {
75    let output = ErrorOutput {
76        schema_version: SCHEMA_VERSION,
77        error: true,
78        code: err.exit_code(),
79        message: err.to_string(),
80        category: err.category().to_string(),
81        retryable: err.retryable(),
82        retry_after_ms: err.retry_after_ms(),
83        hint: err.hint().map(String::from),
84        docs_url: err.docs_url(),
85        correlation_id: correlation_id.to_string(),
86    };
87    let mut stdout = BufWriter::new(io::stdout().lock());
88    serde_json::to_writer(&mut stdout, &output)?;
89    stdout.write_all(b"\n")?;
90    stdout.flush()
91}
92
93pub fn write_models_json(models: &[serde_json::Value], correlation_id: &str) -> io::Result<()> {
94    let envelope = json!({
95        "schema_version": SCHEMA_VERSION,
96        "correlation_id": correlation_id,
97        "models": models,
98    });
99    let mut stdout = BufWriter::new(io::stdout().lock());
100    serde_json::to_writer(&mut stdout, &envelope)?;
101    stdout.write_all(b"\n")?;
102    stdout.flush()
103}
104
105pub fn write_json_value(value: &serde_json::Value) -> io::Result<()> {
106    let mut stdout = BufWriter::new(io::stdout().lock());
107    serde_json::to_writer(&mut stdout, value)?;
108    stdout.write_all(b"\n")?;
109    stdout.flush()
110}
111
112pub fn write_model_status(
113    name: &str,
114    action: &str,
115    path: Option<&str>,
116    correlation_id: &str,
117) -> io::Result<()> {
118    let value = json!({
119        "schema_version": SCHEMA_VERSION,
120        "correlation_id": correlation_id,
121        "model": name,
122        "action": action,
123        "path": path,
124    });
125    write_json_value(&value)
126}