diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index e735ea9a72..f89738b0db 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -1532,6 +1532,8 @@ AUDIO_STT_OPENAI_API_BASE_URL = os.getenv('AUDIO_STT_OPENAI_API_BASE_URL', OPENA AUDIO_STT_OPENAI_API_KEY = os.getenv('AUDIO_STT_OPENAI_API_KEY', OPENAI_API_KEY) +AUDIO_STT_OPENAI_API_REQUEST_FORMAT = os.getenv('AUDIO_STT_OPENAI_API_REQUEST_FORMAT', 'multipart') + AUDIO_STT_ENGINE = os.getenv('AUDIO_STT_ENGINE', '') AUDIO_STT_MODEL = os.getenv('AUDIO_STT_MODEL', '') @@ -2966,6 +2968,7 @@ DEFAULT_CONFIG = { 'audio.stt.deepgram.api_key': DEEPGRAM_API_KEY, 'audio.stt.openai.api_base_url': AUDIO_STT_OPENAI_API_BASE_URL, 'audio.stt.openai.api_key': AUDIO_STT_OPENAI_API_KEY, + 'audio.stt.openai.api_request_format': AUDIO_STT_OPENAI_API_REQUEST_FORMAT, 'audio.stt.engine': AUDIO_STT_ENGINE, 'audio.stt.model': AUDIO_STT_MODEL, 'audio.stt.supported_content_types': AUDIO_STT_SUPPORTED_CONTENT_TYPES, diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py index 8310f49a2c..f062b51a37 100644 --- a/backend/open_webui/routers/audio.py +++ b/backend/open_webui/routers/audio.py @@ -94,6 +94,7 @@ TTS_CONFIG_KEYS = { STT_CONFIG_KEYS = { 'OPENAI_API_BASE_URL': 'audio.stt.openai.api_base_url', 'OPENAI_API_KEY': 'audio.stt.openai.api_key', + 'OPENAI_API_REQUEST_FORMAT': 'audio.stt.openai.api_request_format', 'ENGINE': 'audio.stt.engine', 'MODEL': 'audio.stt.model', 'SUPPORTED_CONTENT_TYPES': 'audio.stt.supported_content_types', @@ -252,6 +253,7 @@ class TTSConfigForm(BaseModel): class STTConfigForm(BaseModel): OPENAI_API_BASE_URL: str OPENAI_API_KEY: str + OPENAI_API_REQUEST_FORMAT: str = 'multipart' ENGINE: str MODEL: str SUPPORTED_CONTENT_TYPES: list[str] = [] @@ -644,28 +646,49 @@ async def _transcribe_openai(request, file_path, filename, languages, file_dir, r = None try: session = await get_session() + api_key = await Config.get('audio.stt.openai.api_key') + api_base_url = await Config.get('audio.stt.openai.api_base_url') + request_format = ( + await Config.get('audio.stt.openai.api_request_format') or 'multipart' + ).lower() + + headers = {'Authorization': f'Bearer {api_key}'} + if user and ENABLE_FORWARD_USER_INFO_HEADERS: + headers = include_user_info_headers(headers, user) + for language in languages: payload = {'model': await Config.get('audio.stt.model')} if language: payload['language'] = language - api_key = await Config.get('audio.stt.openai.api_key') - api_base_url = await Config.get('audio.stt.openai.api_base_url') - headers = {'Authorization': f'Bearer {api_key}'} - if user and ENABLE_FORWARD_USER_INFO_HEADERS: - headers = include_user_info_headers(headers, user) + if request_format == 'json': + ext = os.path.splitext(filename)[1].lower().lstrip('.') or 'wav' + async with aiofiles.open(file_path, 'rb') as f: + payload['input_audio'] = { + 'data': base64.b64encode(await f.read()).decode('utf-8'), + 'format': 'ogg' if ext == 'oga' else ext, + } - form_data = aiohttp.FormData() - for key, value in payload.items(): - form_data.add_field(key, str(value)) - form_data.add_field('file', open(file_path, 'rb'), filename=filename) + r = await session.post( + url=f'{api_base_url}/audio/transcriptions', + headers={**headers, 'Content-Type': 'application/json'}, + json=payload, + ssl=AIOHTTP_CLIENT_SESSION_SSL, + ) + else: + form_data = aiohttp.FormData() + for key, value in payload.items(): + form_data.add_field(key, str(value)) - r = await session.post( - url=f'{api_base_url}/audio/transcriptions', - headers=headers, - data=form_data, - ssl=AIOHTTP_CLIENT_SESSION_SSL, - ) + with open(file_path, 'rb') as audio_file: + form_data.add_field('file', audio_file, filename=filename) + + r = await session.post( + url=f'{api_base_url}/audio/transcriptions', + headers=headers, + data=form_data, + ssl=AIOHTTP_CLIENT_SESSION_SSL, + ) if r.status == 200: break diff --git a/src/lib/components/admin/Settings/Audio.svelte b/src/lib/components/admin/Settings/Audio.svelte index cf893a24b0..a9a7fad001 100644 --- a/src/lib/components/admin/Settings/Audio.svelte +++ b/src/lib/components/admin/Settings/Audio.svelte @@ -43,6 +43,7 @@ let STT_OPENAI_API_BASE_URL = ''; let STT_OPENAI_API_KEY = ''; + let STT_OPENAI_API_REQUEST_FORMAT = 'multipart'; let STT_ENGINE = ''; let STT_MODEL = ''; let STT_SUPPORTED_CONTENT_TYPES = ''; @@ -150,6 +151,7 @@ stt: { OPENAI_API_BASE_URL: STT_OPENAI_API_BASE_URL, OPENAI_API_KEY: STT_OPENAI_API_KEY, + OPENAI_API_REQUEST_FORMAT: STT_OPENAI_API_REQUEST_FORMAT, ENGINE: STT_ENGINE, MODEL: STT_MODEL, SUPPORTED_CONTENT_TYPES: STT_SUPPORTED_CONTENT_TYPES.split(','), @@ -202,6 +204,7 @@ STT_OPENAI_API_BASE_URL = res.stt.OPENAI_API_BASE_URL; STT_OPENAI_API_KEY = res.stt.OPENAI_API_KEY; + STT_OPENAI_API_REQUEST_FORMAT = res.stt.OPENAI_API_REQUEST_FORMAT || 'multipart'; STT_ENGINE = res.stt.ENGINE; STT_MODEL = res.stt.MODEL; @@ -288,6 +291,21 @@