// SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 use derive_builder::Builder; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; use validator::{Validate, ValidationError}; pub trait NvExtProvider { fn nvext(&self) -> Option<&NvExt>; } /// NVIDIA extensions to the Audio Speech API #[derive(ToSchema, Serialize, Deserialize, Builder, Validate, Debug, Clone)] #[validate(schema(function = "validate_nv_ext"))] pub struct NvExt { /// Annotations for SSE stream events #[serde(default, skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub annotations: Option>, /// Language: Auto, Chinese, English, Japanese, Korean, German, French, etc. #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub language: Option, /// Task type: CustomVoice, VoiceDesign, or Base #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub task_type: Option, /// Maximum number of tokens to generate (default: 2048) #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub max_new_tokens: Option, /// Reference audio URL or base64 data (for voice cloning) #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub ref_audio: Option, /// Reference transcript (for voice cloning) #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub ref_text: Option, /// Random seed for reproducibility #[serde(skip_serializing_if = "Option::is_none")] #[builder(default, setter(strip_option))] pub seed: Option, } impl Default for NvExt { fn default() -> Self { NvExt::builder().build().unwrap() } } impl NvExt { pub fn builder() -> NvExtBuilder { NvExtBuilder::default() } } fn validate_nv_ext(_nv_ext: &NvExt) -> Result<(), ValidationError> { Ok(()) } impl NvExtBuilder { pub fn add_annotation(&mut self, annotation: impl Into) -> &mut Self { self.annotations .get_or_insert_with(|| Some(vec![])) .as_mut() .expect("annotations should always be Some(Vec)") .push(annotation.into()); self } }