main: use spooled temp files where possible, instead of "mic.wav"
This commit is contained in:
+35
-6
@@ -10,11 +10,12 @@ use serde::{Deserialize, Serialize};
|
||||
use ratatui::{Frame, layout::{Constraint, Direction, Layout}, widgets::{Block, BorderType, Clear, Gauge, List, ListDirection, ListItem, ListState, Paragraph, Wrap}};
|
||||
use serde_json::Value;
|
||||
use sqlite::OpenFlags;
|
||||
use tempfile::SpooledData;
|
||||
use throbber_widgets_tui::{Throbber, ThrobberState};
|
||||
use crossterm::{event::{self, EventStream, KeyCode, KeyModifiers}};
|
||||
use tokio::{sync::watch, time::Instant};
|
||||
use tui_input::{Input, backend::crossterm::EventHandler};
|
||||
use std::{io::Read, process::Command};
|
||||
use std::{cell::RefCell, io::Read, process::Command, rc::Rc, sync::{Arc, Mutex}};
|
||||
use futures::{StreamExt, future::FutureExt};
|
||||
|
||||
// TODO: We should have a separate 'state.json' file, which remembers jack connections, and the world time for the show to end. Then we only update the 'time remaining' field in the scene and only deal with relative durations inside the scene data
|
||||
@@ -528,6 +529,25 @@ enum AudioRecordRequest {
|
||||
Finish
|
||||
}
|
||||
|
||||
struct RcFile<T>(Arc<Mutex<T>>);
|
||||
|
||||
impl<T: std::io::Write> std::io::Write for RcFile<T> {
|
||||
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
|
||||
self.0.lock().unwrap().write(buf)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> std::io::Result<()> {
|
||||
self.0.lock().unwrap().flush()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: std::io::Seek> std::io::Seek for RcFile<T> {
|
||||
fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
|
||||
self.0.lock().unwrap().seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
color_eyre::install().unwrap();
|
||||
@@ -582,7 +602,9 @@ async fn main() {
|
||||
|
||||
let mut meter = VuMeter::new(rate.into(), 1, None);
|
||||
|
||||
let spool_size = 16 * (rate as usize) * 10;// 10 seconds of audio
|
||||
let mut writer = None;
|
||||
let mut outfile = None;
|
||||
|
||||
let client: Client<OpenAIConfig> = Client::default();
|
||||
|
||||
@@ -592,16 +614,23 @@ async fn main() {
|
||||
let audio_event = maybe_audio_event.unwrap();
|
||||
match audio_event {
|
||||
AudioRecordRequest::Start => {
|
||||
// FIXME: We should switch this over to using spooled tempfiles instead of a named file in the current directory that can easily get clobbered
|
||||
//const SPOOL_SIZE: usize = 16 * (rate as usize) * 10;// 10 seconds of audio
|
||||
//let mut outfile = tempfile::spooled_tempfile(SPOOL_SIZE);
|
||||
writer = Some(hound::WavWriter::create("mic.wav", spec).unwrap());
|
||||
outfile = Some(Arc::new(Mutex::new(tempfile::spooled_tempfile(spool_size))));
|
||||
writer = Some(hound::WavWriter::new(RcFile(outfile.as_ref().unwrap().clone()), spec).unwrap());
|
||||
},
|
||||
AudioRecordRequest::Finish => {
|
||||
writer = None;
|
||||
|
||||
let final_audio = outfile.take().unwrap();
|
||||
let bytes = match Arc::into_inner(final_audio).unwrap().into_inner().unwrap().into_inner() {
|
||||
SpooledData::OnDisk(mut file) => {
|
||||
let mut bytes = Vec::new();
|
||||
file.read_to_end(&mut bytes).unwrap();
|
||||
bytes.into()
|
||||
},
|
||||
SpooledData::InMemory(cursor) => cursor.into_inner().into(),
|
||||
};
|
||||
let response = client.audio().transcription().create(CreateTranscriptionRequest {
|
||||
file: AudioInput { source: InputSource::Path { path: "mic.wav".into() } },
|
||||
file: AudioInput { source: InputSource::Bytes { filename: "transcription.wav".into(), bytes } },
|
||||
model: "gpt-4o-mini-transcribe".into(),
|
||||
..Default::default()
|
||||
}).await.unwrap();
|
||||
|
||||
Reference in New Issue
Block a user