diff --git a/crates/live/src/server.rs b/crates/live/src/server.rs index 972fa558..35af79ea 100644 --- a/crates/live/src/server.rs +++ b/crates/live/src/server.rs @@ -9,6 +9,7 @@ use tracing::info; use crate::{LiveEvent, LiveState}; +mod audio; mod cors; mod drivers; mod health; @@ -58,6 +59,7 @@ pub async fn init( let app = Router::new() .route("/api/sse", get(live::sse_handler)) .route("/api/health", get(health::check)) + .route("/api/audio", get(audio::get_audio)) .route("/api/drivers", get(drivers::get_drivers)) .layer(cors) .layer(governor) diff --git a/crates/live/src/server/audio.rs b/crates/live/src/server/audio.rs new file mode 100644 index 00000000..d86e1e0f --- /dev/null +++ b/crates/live/src/server/audio.rs @@ -0,0 +1,29 @@ +use axum::{extract::Query, http::StatusCode, response::IntoResponse}; +use serde::Deserialize; +use std::env; +use tracing::error; + +#[derive(Deserialize)] +pub struct Params { + path: String, +} + +pub async fn get_audio(Query(params): Query) -> Result { + let Ok(_) = env::var("ENABLE_AUDIO_FETCH") else { + return Err(StatusCode::NOT_IMPLEMENTED); + }; + + let audio_url = format!("https://livetiming.formula1.com/static/{}", params.path); + + let Ok(response) = reqwest::get(&audio_url).await else { + error!("Failed to retrieve audio data from {}", audio_url); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + }; + + let Ok(bytes) = response.bytes().await else { + error!("Failed to decode response from {}", audio_url); + return Err(StatusCode::INTERNAL_SERVER_ERROR); + }; + + Ok(bytes.as_ref().to_vec()) +} diff --git a/dash/next.config.mjs b/dash/next.config.mjs index 5ed1b05b..573af62f 100644 --- a/dash/next.config.mjs +++ b/dash/next.config.mjs @@ -5,6 +5,16 @@ await import("./src/env.mjs"); /** @type {import("next").NextConfig} */ const config = { reactStrictMode: false, + webpack: ( + config, + ) => { + config.resolve.alias = { + ...config.resolve.alias, + "sharp$": false, + "onnxruntime-node$": false, + } + return config + }, output: process.env.BUILD_STANDALONE === "1" ? "standalone" : undefined, env: { version: pack.version, diff --git a/dash/package.json b/dash/package.json index b7fc8b56..5002fd51 100644 --- a/dash/package.json +++ b/dash/package.json @@ -12,6 +12,7 @@ "dependencies": { "@fireworks-js/react": "2.10.8", "@headlessui/react": "2.2.0", + "@xenova/transformers": "2.7.0", "clsx": "2.1.1", "framer-motion": "11.11.17", "geist": "1.3.1", diff --git a/dash/src/app/(nav)/settings/page.tsx b/dash/src/app/(nav)/settings/page.tsx index bfde0429..d1897072 100644 --- a/dash/src/app/(nav)/settings/page.tsx +++ b/dash/src/app/(nav)/settings/page.tsx @@ -18,13 +18,19 @@ import Toggle from "@/components/Toggle"; import Footer from "@/components/Footer"; import Slider from "@/components/Slider"; import Input from "@/components/Input"; +import Select from "@/components/Select"; + import { useSettingsStore } from "@/stores/useSettingsStore"; +import { models, useTranscriptionStore } from "@/stores/useTranscriptionStore"; import { env } from "@/env.mjs"; export default function SettingsPage() { const settings = useSettingsStore(); + + const transcription = useTranscriptionStore(); + return (

Settings

@@ -117,6 +123,20 @@ export default function SettingsPage() { Reset delay +

Enable Radio Transcription

+ +

Only available when the corresponding feature is enabled from server.

+ +
+ transcription.setEnabled(v)} /> +

Enable Radio Transcription

+
+ +
+