import { IsBase64, IsIn, IsInt, IsString, MaxLength, Min, } from 'class-validator'; /** Containers OpenRouter's transcription endpoint accepts, and MediaRecorder can produce. */ export const VOICE_AUDIO_FORMATS = [ 'webm', 'mp4', 'm4a', 'aac', 'ogg', 'wav', 'mp3', 'flac', ] as const; export type VoiceAudioFormat = (typeof VOICE_AUDIO_FORMATS)[number]; export class ExtractVoiceDto { /** * Base64 audio, no data: prefix. Capped well above a 2-minute opus clip (~400 KB) but * far below OpenRouter's 25 MB ceiling, so an oversized upload is rejected before it * costs a vendor call. */ @IsString() @IsBase64() @MaxLength(8_000_000) audio: string; @IsIn(VOICE_AUDIO_FORMATS) format: VoiceAudioFormat; /** * The clinician's IANA zone. The server derives "today" from it rather than trusting a * client-supplied date, which is what relative deadlines resolve against. */ @IsString() @MaxLength(64) timeZone: string; /** * Recording length as measured by the client. * * Required, not optional: an optional value means omitting it bypasses * VOICE_MAX_RECORDING_MS entirely, which would make the cap advisory. */ @IsInt() @Min(0) durationMs: number; }