From 43f7ff500171d0ada1835e98f5e53abba0c07020 Mon Sep 17 00:00:00 2001 From: CSantosM <4a.santos@gmail.com> Date: Wed, 28 Jan 2026 15:21:00 +0100 Subject: [PATCH] backend: Exposes captions config via internal API Adds an internal API endpoint to retrieve the captions configuration, allowing the frontend to determine whether captions are enabled. The configuration is read from the MEET_CAPTIONS_ENABLED environment variable. --- .../internal/success-get-captions-config.yaml | 5 ++++ .../internal/global-captions-config.yaml | 8 +++++++ .../openapi/openvidu-meet-internal-api.yaml | 2 ++ .../paths/internal/meet-global-config.yaml | 17 ++++++++++++++ .../controllers/global-config.controller.ts | 14 +++++++++++ meet-ce/backend/src/environment.ts | 5 ++-- .../src/routes/global-config.routes.ts | 3 +++ .../backend/tests/helpers/request-helpers.ts | 7 ++++++ .../api/global-config/captions.test.ts | 23 +++++++++++++++++++ 9 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 meet-ce/backend/openapi/components/responses/internal/success-get-captions-config.yaml create mode 100644 meet-ce/backend/openapi/components/schemas/internal/global-captions-config.yaml create mode 100644 meet-ce/backend/tests/integration/api/global-config/captions.test.ts diff --git a/meet-ce/backend/openapi/components/responses/internal/success-get-captions-config.yaml b/meet-ce/backend/openapi/components/responses/internal/success-get-captions-config.yaml new file mode 100644 index 00000000..1d156c57 --- /dev/null +++ b/meet-ce/backend/openapi/components/responses/internal/success-get-captions-config.yaml @@ -0,0 +1,5 @@ +description: Successfully retrieved captions config +content: + application/json: + schema: + $ref: '../../schemas/internal/global-captions-config.yaml' diff --git a/meet-ce/backend/openapi/components/schemas/internal/global-captions-config.yaml b/meet-ce/backend/openapi/components/schemas/internal/global-captions-config.yaml new file mode 100644 index 00000000..e544a4fb --- /dev/null +++ b/meet-ce/backend/openapi/components/schemas/internal/global-captions-config.yaml @@ -0,0 +1,8 @@ +type: object +properties: + enabled: + type: boolean + description: Indicates whether captions are enabled in the system + example: true +required: + - enabled diff --git a/meet-ce/backend/openapi/openvidu-meet-internal-api.yaml b/meet-ce/backend/openapi/openvidu-meet-internal-api.yaml index b5b1b995..96f13ffa 100644 --- a/meet-ce/backend/openapi/openvidu-meet-internal-api.yaml +++ b/meet-ce/backend/openapi/openvidu-meet-internal-api.yaml @@ -32,6 +32,8 @@ paths: $ref: './paths/internal/meet-global-config.yaml#/~1config~1security' /config/rooms/appearance: $ref: './paths/internal/meet-global-config.yaml#/~1config~1rooms~1appearance' + /config/captions: + $ref: './paths/internal/meet-global-config.yaml#/~1config~1captions' /rooms/{roomId}/token: $ref: './paths/internal/rooms.yaml#/~1rooms~1{roomId}~1token' /meetings/{roomId}: diff --git a/meet-ce/backend/openapi/paths/internal/meet-global-config.yaml b/meet-ce/backend/openapi/paths/internal/meet-global-config.yaml index 2b409ca2..9c2496f1 100644 --- a/meet-ce/backend/openapi/paths/internal/meet-global-config.yaml +++ b/meet-ce/backend/openapi/paths/internal/meet-global-config.yaml @@ -139,3 +139,20 @@ $ref: '../../components/responses/validation-error.yaml' '500': $ref: '../../components/responses/internal-server-error.yaml' + +/config/captions: + get: + operationId: getCaptionsConfig + summary: Get captions config + description: > + Retrieves the captions configuration from the environment variable MEET_CAPTIONS_ENABLED. + This endpoint returns whether captions are enabled in the system. + tags: + - Internal API - Global Config + responses: + '200': + $ref: '../../components/responses/internal/success-get-captions-config.yaml' + '401': + $ref: '../../components/responses/unauthorized-error.yaml' + '500': + $ref: '../../components/responses/internal-server-error.yaml' diff --git a/meet-ce/backend/src/controllers/global-config.controller.ts b/meet-ce/backend/src/controllers/global-config.controller.ts index 53920b73..5874b4cb 100644 --- a/meet-ce/backend/src/controllers/global-config.controller.ts +++ b/meet-ce/backend/src/controllers/global-config.controller.ts @@ -1,6 +1,7 @@ import { MeetAppearanceConfig, SecurityConfig, WebhookConfig } from '@openvidu-meet/typings'; import { Request, Response } from 'express'; import { container } from '../config/dependency-injector.config.js'; +import { MEET_ENV } from '../environment.js'; import { handleError } from '../models/error.model.js'; import { GlobalConfigService } from '../services/global-config.service.js'; import { LoggerService } from '../services/logger.service.js'; @@ -108,3 +109,16 @@ export const getRoomsAppearanceConfig = async (_req: Request, res: Response) => handleError(res, error, 'getting rooms appearance config'); } }; + +export const getCaptionsConfig = async (_req: Request, res: Response) => { + const logger = container.get(LoggerService); + + logger.verbose('Getting captions config'); + + try { + const captionsEnabled = MEET_ENV.CAPTIONS_ENABLED === 'true'; + return res.status(200).json({ enabled: captionsEnabled }); + } catch (error) { + handleError(res, error, 'getting captions config'); + } +}; diff --git a/meet-ce/backend/src/environment.ts b/meet-ce/backend/src/environment.ts index 43fcd499..8a2e2d2d 100644 --- a/meet-ce/backend/src/environment.ts +++ b/meet-ce/backend/src/environment.ts @@ -79,13 +79,14 @@ export const MEET_ENV = { REDIS_SENTINEL_PASSWORD: process.env.MEET_REDIS_SENTINEL_PASSWORD ?? '', REDIS_SENTINEL_MASTER_NAME: process.env.MEET_REDIS_SENTINEL_MASTER_NAME ?? 'openvidu', + // Live Captions configuration + CAPTIONS_ENABLED: process.env.MEET_CAPTIONS_ENABLED || 'false', + // Deployment configuration MODULES_FILE: process.env.MODULES_FILE || undefined, MODULE_NAME: process.env.MODULE_NAME || 'openviduMeet', ENABLED_MODULES: process.env.ENABLED_MODULES ?? '', - // Agent Speech Processing configuration - CAPTIONS_ENABLED: process.env.MEET_CAPTIONS || 'true', }; export function checkModuleEnabled() { diff --git a/meet-ce/backend/src/routes/global-config.routes.ts b/meet-ce/backend/src/routes/global-config.routes.ts index edc50cff..1ba95d8a 100644 --- a/meet-ce/backend/src/routes/global-config.routes.ts +++ b/meet-ce/backend/src/routes/global-config.routes.ts @@ -41,3 +41,6 @@ configRouter.put( globalConfigCtrl.updateRoomsAppearanceConfig ); configRouter.get('/rooms/appearance', withAuth(allowAnonymous), globalConfigCtrl.getRoomsAppearanceConfig); + +// Captions config +configRouter.get('/captions', withAuth(allowAnonymous), globalConfigCtrl.getCaptionsConfig); diff --git a/meet-ce/backend/tests/helpers/request-helpers.ts b/meet-ce/backend/tests/helpers/request-helpers.ts index 75ea3751..7c88047b 100644 --- a/meet-ce/backend/tests/helpers/request-helpers.ts +++ b/meet-ce/backend/tests/helpers/request-helpers.ts @@ -184,6 +184,13 @@ export const changeSecurityConfig = async (authMode: AuthMode) => { expect(response.status).toBe(200); }; +export const getCaptionsConfig = async () => { + checkAppIsRunning(); + + const response = await request(app).get(`${INTERNAL_CONFIG.INTERNAL_API_BASE_PATH_V1}/config/captions`).send(); + return response; +}; + export const restoreDefaultGlobalConfig = async () => { const configService = container.get(GlobalConfigService); const defaultGlobalConfig = configService['getDefaultConfig'](); diff --git a/meet-ce/backend/tests/integration/api/global-config/captions.test.ts b/meet-ce/backend/tests/integration/api/global-config/captions.test.ts new file mode 100644 index 00000000..ed19c6ef --- /dev/null +++ b/meet-ce/backend/tests/integration/api/global-config/captions.test.ts @@ -0,0 +1,23 @@ +import { beforeAll, describe, expect, it } from '@jest/globals'; +import { getCaptionsConfig, startTestServer } from '../../../helpers/request-helpers.js'; + +describe('Captions Config API Tests', () => { + beforeAll(async () => { + await startTestServer(); + }); + + describe('Get captions config', () => { + it('should return captions config when not authenticated', async () => { + const response = await getCaptionsConfig(); + expect(response.status).toBe(200); + expect(response.body).toHaveProperty('enabled'); + expect(typeof response.body.enabled).toBe('boolean'); + }); + + it('should return enabled true by default', async () => { + const response = await getCaptionsConfig(); + expect(response.status).toBe(200); + expect(response.body).toEqual({ enabled: true }); + }); + }); +});