From fabc35e2578b472a5543a6bb08e26c3856ba6397 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:27:05 +0300 Subject: [PATCH 01/22] OV-173: + types --- .../src/bundles/avatar-videos/types/types.ts | 6 ++++++ .../render-avatar-video-api-argument.type.ts | 8 ++++++++ .../render-avatar-video-api-request-dto.type.ts | 16 ++++++++++++++++ ...ender-avatar-video-api-response-dto.type.ts} | 4 ++-- .../types/render-avatar-video-arguments.type.ts | 2 +- .../apis/avatar-video/libs/types/types.ts | 11 +++++++++++ .../render-avatar-video-request-dto.type.ts | 17 ----------------- .../src/common/services/azure-ai/types/types.ts | 6 ------ shared/src/bundles/avatar-video/avatar-video.ts | 2 -- shared/src/bundles/avatar-video/types/types.ts | 2 -- .../avatar-videos}/types/avatar-config.type.ts | 0 .../types/get-avatar-video-request-dto.type.ts | 0 .../types/get-avatar-video-response-dto.type.ts | 0 .../avatar-videos}/types/input-kind.type.ts | 0 .../types/render-avatar-request-dto.type.ts | 8 ++++++++ .../types/render-avatar-response-dto.type.ts | 5 +++++ .../types/video-codec.type.ts | 0 .../types/video-format.type.ts | 0 18 files changed, 57 insertions(+), 30 deletions(-) create mode 100644 backend/src/bundles/avatar-videos/types/types.ts create mode 100644 backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-argument.type.ts create mode 100644 backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-request-dto.type.ts rename backend/src/common/services/azure-ai/{types/render-avatar-video-response-dto.type.ts => apis/avatar-video/libs/types/render-avatar-video-api-response-dto.type.ts} (85%) delete mode 100644 backend/src/common/services/azure-ai/types/render-avatar-video-request-dto.type.ts delete mode 100644 shared/src/bundles/avatar-video/avatar-video.ts delete mode 100644 shared/src/bundles/avatar-video/types/types.ts rename {backend/src/common/services/azure-ai => shared/src/bundles/avatar-videos}/types/avatar-config.type.ts (100%) rename {backend/src/common/services/azure-ai => shared/src/bundles/avatar-videos}/types/get-avatar-video-request-dto.type.ts (100%) rename {backend/src/common/services/azure-ai => shared/src/bundles/avatar-videos}/types/get-avatar-video-response-dto.type.ts (100%) rename {backend/src/common/services/azure-ai => shared/src/bundles/avatar-videos}/types/input-kind.type.ts (100%) create mode 100644 shared/src/bundles/avatar-videos/types/render-avatar-request-dto.type.ts create mode 100644 shared/src/bundles/avatar-videos/types/render-avatar-response-dto.type.ts rename shared/src/bundles/{avatar-video => avatar-videos}/types/video-codec.type.ts (100%) rename shared/src/bundles/{avatar-video => avatar-videos}/types/video-format.type.ts (100%) diff --git a/backend/src/bundles/avatar-videos/types/types.ts b/backend/src/bundles/avatar-videos/types/types.ts new file mode 100644 index 000000000..cdbb67a6e --- /dev/null +++ b/backend/src/bundles/avatar-videos/types/types.ts @@ -0,0 +1,6 @@ +export { + type GetAvatarVideoRequestDto, + type GetAvatarVideoResponseDto, + type RenderAvatarResponseDto, + type RenderAvatarVideoRequestDto, +} from 'shared'; diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-argument.type.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-argument.type.ts new file mode 100644 index 000000000..c1f8d7d61 --- /dev/null +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-argument.type.ts @@ -0,0 +1,8 @@ +import { type RenderAvatarVideoApiRequestDto } from './types.js'; + +type RenderAvatarVideoApiArgument = { + id: string; + payload: RenderAvatarVideoApiRequestDto; +}; + +export { type RenderAvatarVideoApiArgument }; diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-request-dto.type.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-request-dto.type.ts new file mode 100644 index 000000000..150b3c714 --- /dev/null +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-request-dto.type.ts @@ -0,0 +1,16 @@ +import { type AvatarConfig, type InputKind } from './types.js'; + +type RenderAvatarVideoApiRequestDto = { + inputKind: InputKind; + synthesisConfig: { + voice: string; + }; + inputs: [ + { + content: string; + }, + ]; + avatarConfig: AvatarConfig; +}; + +export { type RenderAvatarVideoApiRequestDto }; diff --git a/backend/src/common/services/azure-ai/types/render-avatar-video-response-dto.type.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-response-dto.type.ts similarity index 85% rename from backend/src/common/services/azure-ai/types/render-avatar-video-response-dto.type.ts rename to backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-response-dto.type.ts index f60371ad9..19cb52a8d 100644 --- a/backend/src/common/services/azure-ai/types/render-avatar-video-response-dto.type.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-api-response-dto.type.ts @@ -1,6 +1,6 @@ import { type InputKind, type VideoCodec, type VideoFormat } from './types.js'; -type RenderAvatarVideoResponseDto = { +type RenderAvatarVideoApiResponseDto = { id: string; internalId: string; status: string; @@ -21,4 +21,4 @@ type RenderAvatarVideoResponseDto = { }; }; -export { type RenderAvatarVideoResponseDto }; +export { type RenderAvatarVideoApiResponseDto }; diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-arguments.type.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-arguments.type.ts index c503994d1..88fc0d9da 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-arguments.type.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/render-avatar-video-arguments.type.ts @@ -1,4 +1,4 @@ -import { type RenderAvatarVideoRequestDto } from '~/common/services/azure-ai/types/types.js'; +import { type RenderAvatarVideoRequestDto } from './types.js'; type RenderAvatarVideoArgument = { id: string; diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts index 3bf47cd7b..cb2cd3baf 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts @@ -1 +1,12 @@ +export { type RenderAvatarVideoApiArgument } from './render-avatar-video-api-argument.type.js'; +export { type RenderAvatarVideoApiRequestDto } from './render-avatar-video-api-request-dto.type.js'; +export { type RenderAvatarVideoApiResponseDto } from './render-avatar-video-api-response-dto.type.js'; export { type RenderAvatarVideoArgument } from './render-avatar-video-arguments.type.js'; +export { type GetAvatarVideoResponseDto } from 'shared'; +export { + type AvatarConfig, + type InputKind, + type RenderAvatarVideoRequestDto, + type VideoCodec, + type VideoFormat, +} from 'shared'; diff --git a/backend/src/common/services/azure-ai/types/render-avatar-video-request-dto.type.ts b/backend/src/common/services/azure-ai/types/render-avatar-video-request-dto.type.ts deleted file mode 100644 index cd1becff4..000000000 --- a/backend/src/common/services/azure-ai/types/render-avatar-video-request-dto.type.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { type AvatarConfig } from './avatar-config.type.js'; -import { type InputKind } from './input-kind.type.js'; - -type RenderAvatarVideoRequestDto = { - inputKind: InputKind; - synthesisConfig: { - voice: string; - }; - inputs: [ - { - content: string; - }, - ]; - avatarConfig: AvatarConfig; -}; - -export { type RenderAvatarVideoRequestDto }; diff --git a/backend/src/common/services/azure-ai/types/types.ts b/backend/src/common/services/azure-ai/types/types.ts index 2d648dd22..f80016532 100644 --- a/backend/src/common/services/azure-ai/types/types.ts +++ b/backend/src/common/services/azure-ai/types/types.ts @@ -1,7 +1 @@ export { type AzureGetVoicesResponseDto } from './azure-get-voices-response-dto.type.js'; -export { type GetAvatarVideoRequestDto } from './get-avatar-video-request-dto.type.js'; -export { type GetAvatarVideoResponseDto } from './get-avatar-video-response-dto.type.js'; -export { type InputKind } from './input-kind.type.js'; -export { type RenderAvatarVideoRequestDto } from './render-avatar-video-request-dto.type.js'; -export { type RenderAvatarVideoResponseDto } from './render-avatar-video-response-dto.type.js'; -export { type VideoCodec, type VideoFormat } from 'shared'; diff --git a/shared/src/bundles/avatar-video/avatar-video.ts b/shared/src/bundles/avatar-video/avatar-video.ts deleted file mode 100644 index cc7a473bc..000000000 --- a/shared/src/bundles/avatar-video/avatar-video.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { type VideoFormat } from './types/types.js'; -export { type VideoCodec } from './types/types.js'; diff --git a/shared/src/bundles/avatar-video/types/types.ts b/shared/src/bundles/avatar-video/types/types.ts deleted file mode 100644 index e4e95edb2..000000000 --- a/shared/src/bundles/avatar-video/types/types.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { type VideoCodec } from './video-codec.type.js'; -export { type VideoFormat } from './video-format.type.js'; diff --git a/backend/src/common/services/azure-ai/types/avatar-config.type.ts b/shared/src/bundles/avatar-videos/types/avatar-config.type.ts similarity index 100% rename from backend/src/common/services/azure-ai/types/avatar-config.type.ts rename to shared/src/bundles/avatar-videos/types/avatar-config.type.ts diff --git a/backend/src/common/services/azure-ai/types/get-avatar-video-request-dto.type.ts b/shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts similarity index 100% rename from backend/src/common/services/azure-ai/types/get-avatar-video-request-dto.type.ts rename to shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts diff --git a/backend/src/common/services/azure-ai/types/get-avatar-video-response-dto.type.ts b/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts similarity index 100% rename from backend/src/common/services/azure-ai/types/get-avatar-video-response-dto.type.ts rename to shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts diff --git a/backend/src/common/services/azure-ai/types/input-kind.type.ts b/shared/src/bundles/avatar-videos/types/input-kind.type.ts similarity index 100% rename from backend/src/common/services/azure-ai/types/input-kind.type.ts rename to shared/src/bundles/avatar-videos/types/input-kind.type.ts diff --git a/shared/src/bundles/avatar-videos/types/render-avatar-request-dto.type.ts b/shared/src/bundles/avatar-videos/types/render-avatar-request-dto.type.ts new file mode 100644 index 000000000..2edf55be1 --- /dev/null +++ b/shared/src/bundles/avatar-videos/types/render-avatar-request-dto.type.ts @@ -0,0 +1,8 @@ +type RenderAvatarVideoRequestDto = { + avatarName: string; + avatarStyle: string; + text: string; + voice: string; +}; + +export { type RenderAvatarVideoRequestDto }; diff --git a/shared/src/bundles/avatar-videos/types/render-avatar-response-dto.type.ts b/shared/src/bundles/avatar-videos/types/render-avatar-response-dto.type.ts new file mode 100644 index 000000000..b19d54227 --- /dev/null +++ b/shared/src/bundles/avatar-videos/types/render-avatar-response-dto.type.ts @@ -0,0 +1,5 @@ +type RenderAvatarResponseDto = { + id: string; +}; + +export { type RenderAvatarResponseDto }; diff --git a/shared/src/bundles/avatar-video/types/video-codec.type.ts b/shared/src/bundles/avatar-videos/types/video-codec.type.ts similarity index 100% rename from shared/src/bundles/avatar-video/types/video-codec.type.ts rename to shared/src/bundles/avatar-videos/types/video-codec.type.ts diff --git a/shared/src/bundles/avatar-video/types/video-format.type.ts b/shared/src/bundles/avatar-videos/types/video-format.type.ts similarity index 100% rename from shared/src/bundles/avatar-video/types/video-format.type.ts rename to shared/src/bundles/avatar-videos/types/video-format.type.ts From 6289479e8b15447b8b58da6991392dec8942e5af Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:31:58 +0300 Subject: [PATCH 02/22] OV-173: + constants --- .../azure-ai/constants/avatar-input-kind.constant.ts | 3 +++ .../azure-ai/constants/avatar-subtitle-type.constant.ts | 3 +++ .../azure-ai/constants/avatar-video-codec.constant.ts | 3 +++ .../azure-ai/constants/avatar-video-format.constant.ts | 3 +++ backend/src/common/services/azure-ai/constants/constants.ts | 5 +++++ 5 files changed, 17 insertions(+) create mode 100644 backend/src/common/services/azure-ai/constants/avatar-input-kind.constant.ts create mode 100644 backend/src/common/services/azure-ai/constants/avatar-subtitle-type.constant.ts create mode 100644 backend/src/common/services/azure-ai/constants/avatar-video-codec.constant.ts create mode 100644 backend/src/common/services/azure-ai/constants/avatar-video-format.constant.ts create mode 100644 backend/src/common/services/azure-ai/constants/constants.ts diff --git a/backend/src/common/services/azure-ai/constants/avatar-input-kind.constant.ts b/backend/src/common/services/azure-ai/constants/avatar-input-kind.constant.ts new file mode 100644 index 000000000..0abdb4bcb --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/avatar-input-kind.constant.ts @@ -0,0 +1,3 @@ +const AVATAR_INPUT_KIND = 'PlainText'; + +export { AVATAR_INPUT_KIND }; diff --git a/backend/src/common/services/azure-ai/constants/avatar-subtitle-type.constant.ts b/backend/src/common/services/azure-ai/constants/avatar-subtitle-type.constant.ts new file mode 100644 index 000000000..acd37b3a6 --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/avatar-subtitle-type.constant.ts @@ -0,0 +1,3 @@ +const AVATAR_SUBTITLE_TYPE = 'soft_embedded'; + +export { AVATAR_SUBTITLE_TYPE }; diff --git a/backend/src/common/services/azure-ai/constants/avatar-video-codec.constant.ts b/backend/src/common/services/azure-ai/constants/avatar-video-codec.constant.ts new file mode 100644 index 000000000..2d75dc050 --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/avatar-video-codec.constant.ts @@ -0,0 +1,3 @@ +const AVATAR_VIDEO_CODEC = 'vp9'; + +export { AVATAR_VIDEO_CODEC }; diff --git a/backend/src/common/services/azure-ai/constants/avatar-video-format.constant.ts b/backend/src/common/services/azure-ai/constants/avatar-video-format.constant.ts new file mode 100644 index 000000000..820da4045 --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/avatar-video-format.constant.ts @@ -0,0 +1,3 @@ +const AVATAR_VIDEO_FORMAT = 'webm'; + +export { AVATAR_VIDEO_FORMAT }; diff --git a/backend/src/common/services/azure-ai/constants/constants.ts b/backend/src/common/services/azure-ai/constants/constants.ts new file mode 100644 index 000000000..e6d136dc7 --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/constants.ts @@ -0,0 +1,5 @@ +export { AVATAR_BACKGROUND_COLOR } from './avatar-background-color.constant.js'; +export { AVATAR_INPUT_KIND } from './avatar-input-kind.constant.js'; +export { AVATAR_SUBTITLE_TYPE } from './avatar-subtitle-type.constant.js'; +export { AVATAR_VIDEO_CODEC } from './avatar-video-codec.constant.js'; +export { AVATAR_VIDEO_FORMAT } from './avatar-video-format.constant.js'; From 44b1c01e8e4eaaae148d5bc4775c5403802f4d51 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:34:17 +0300 Subject: [PATCH 03/22] OV-173: + constants --- .../azure-ai/constants/avatar-background-color.constant.ts | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backend/src/common/services/azure-ai/constants/avatar-background-color.constant.ts diff --git a/backend/src/common/services/azure-ai/constants/avatar-background-color.constant.ts b/backend/src/common/services/azure-ai/constants/avatar-background-color.constant.ts new file mode 100644 index 000000000..6dee9e36e --- /dev/null +++ b/backend/src/common/services/azure-ai/constants/avatar-background-color.constant.ts @@ -0,0 +1,3 @@ +const AVATAR_BACKGROUND_COLOR = 'transparent'; + +export { AVATAR_BACKGROUND_COLOR }; From cc28bcfcb902ecc38d76f8599c2fa45e47e06e9c Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:35:42 +0300 Subject: [PATCH 04/22] OV-173: + getAvatarConfig helper --- .../azure-ai/helpers/get-avatar-config.ts | 38 +++++++++++++++++++ .../services/azure-ai/helpers/helpers.ts | 1 + 2 files changed, 39 insertions(+) create mode 100644 backend/src/common/services/azure-ai/helpers/get-avatar-config.ts create mode 100644 backend/src/common/services/azure-ai/helpers/helpers.ts diff --git a/backend/src/common/services/azure-ai/helpers/get-avatar-config.ts b/backend/src/common/services/azure-ai/helpers/get-avatar-config.ts new file mode 100644 index 000000000..7848364d7 --- /dev/null +++ b/backend/src/common/services/azure-ai/helpers/get-avatar-config.ts @@ -0,0 +1,38 @@ +import { + type RenderAvatarVideoApiRequestDto, + type RenderAvatarVideoRequestDto, +} from '../apis/avatar-video/libs/types/types.js'; +import { + AVATAR_BACKGROUND_COLOR, + AVATAR_INPUT_KIND, + AVATAR_SUBTITLE_TYPE, + AVATAR_VIDEO_CODEC, + AVATAR_VIDEO_FORMAT, +} from '../constants/constants.js'; + +const getAvatarConfig = ( + payload: RenderAvatarVideoRequestDto, +): RenderAvatarVideoApiRequestDto => { + const { avatarName, avatarStyle, text, voice } = payload; + return { + inputKind: AVATAR_INPUT_KIND, + synthesisConfig: { + voice, + }, + avatarConfig: { + talkingAvatarCharacter: avatarName, + talkingAvatarStyle: avatarStyle, + backgroundColor: AVATAR_BACKGROUND_COLOR, + subtitleType: AVATAR_SUBTITLE_TYPE, + videoCodec: AVATAR_VIDEO_CODEC, + videoFormat: AVATAR_VIDEO_FORMAT, + }, + inputs: [ + { + content: text, + }, + ], + }; +}; + +export { getAvatarConfig }; diff --git a/backend/src/common/services/azure-ai/helpers/helpers.ts b/backend/src/common/services/azure-ai/helpers/helpers.ts new file mode 100644 index 000000000..ea8c7e2c4 --- /dev/null +++ b/backend/src/common/services/azure-ai/helpers/helpers.ts @@ -0,0 +1 @@ +export { getAvatarConfig } from './get-avatar-config.js'; From 5d0221d4075bf32fff8529e7078967d18eef6103 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:37:25 +0300 Subject: [PATCH 05/22] OV-173: * avatar-video-api --- .../apis/avatar-video/avatar-video-api.ts | 24 +++++++++++++------ .../apis/avatar-video/avatar-video.ts | 8 +++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts index 3474169ff..a0628c127 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts @@ -3,13 +3,13 @@ import { ApiPath, ContentType, HttpHeader, HTTPMethod } from 'shared'; import { config } from '~/common/config/config.js'; import { BaseHttpApi } from '~/common/http/http.js'; -import { - type GetAvatarVideoResponseDto, - type RenderAvatarVideoResponseDto, -} from '~/common/services/azure-ai/types/types.js'; import { AvatarApiPath } from './libs/enums/enums.js'; -import { type RenderAvatarVideoArgument } from './libs/types/types.js'; +import { + type GetAvatarVideoResponseDto, + type RenderAvatarVideoApiArgument, + type RenderAvatarVideoApiResponseDto, +} from './libs/types/types.js'; type Constructor = { baseUrl: string; @@ -66,7 +66,7 @@ class AvatarVideoApi extends BaseHttpApi { public async renderAvatarVideo({ id, payload, - }: RenderAvatarVideoArgument): Promise { + }: RenderAvatarVideoApiArgument): Promise { const response = await this.load( this.getFullEndpoint( `${AvatarApiPath.BATCHSYNTHESES}/${id}?api-version=2024-08-01`, @@ -85,7 +85,17 @@ class AvatarVideoApi extends BaseHttpApi { }, ); - return await response.json(); + return await response.json(); + } + + public async getAvatarVideoBuffer(url: string): Promise { + const response = await this.load(url, { + method: HTTPMethod.GET, + contentType: ContentType.JSON, + }); + + const arrayBuffer = await response.arrayBuffer(); + return Buffer.from(arrayBuffer); } } diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts index 82082988b..6c4af971f 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts @@ -9,3 +9,11 @@ const avatarVideoApi = new AvatarVideoApi({ }); export { avatarVideoApi }; +export { AvatarVideoApi } from './avatar-video-api.js'; +export { AvatarApiPath } from './libs/enums/enums.js'; +export { + type GetAvatarVideoResponseDto, + type RenderAvatarVideoApiRequestDto, + type RenderAvatarVideoApiResponseDto, + type RenderAvatarVideoArgument, +} from './libs/types/types.js'; From 145c6726098b360e229a84206a860aff5fad96e9 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:38:21 +0300 Subject: [PATCH 06/22] OV-173: + validdation schema --- .../render-avatar-video.validation-schema.ts | 50 +++++++++++++++++++ .../validation-schemas/validation-schemas.ts | 1 + 2 files changed, 51 insertions(+) create mode 100644 shared/src/bundles/avatar-videos/validation-schemas/render-avatar-video.validation-schema.ts create mode 100644 shared/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts diff --git a/shared/src/bundles/avatar-videos/validation-schemas/render-avatar-video.validation-schema.ts b/shared/src/bundles/avatar-videos/validation-schemas/render-avatar-video.validation-schema.ts new file mode 100644 index 000000000..7a9a06ecb --- /dev/null +++ b/shared/src/bundles/avatar-videos/validation-schemas/render-avatar-video.validation-schema.ts @@ -0,0 +1,50 @@ +import { z } from 'zod'; + +import { AvatarVideoValidationMessage } from '../enum/enums.js'; + +type GenerateAvatarVideoRequestValidationDto = { + avatarName: z.ZodString; + avatarStyle: z.ZodString; + text: z.ZodString; + voice: z.ZodString; +}; + +const renderAvatarVideo = z + .object({ + text: z.string().trim().min(1, { + message: AvatarVideoValidationMessage.TEXT_REQUIRED, + }), + avatarName: z.string().trim().min(1, { + message: AvatarVideoValidationMessage.AVATAR_NAME_REQUIRED, + }), + avatarStyle: z.string().trim().min(1, { + message: AvatarVideoValidationMessage.AVATAR_STYLE_REQUIRED, + }), + voice: z.string().trim().min(1, { + message: AvatarVideoValidationMessage.VOICE_NAME_REQUIRED, + }), + }) + .required() + .refine( + ({ voice }) => { + const splittedVoiceName = voice.split('-'); + + if (splittedVoiceName.length !== 3) { + return false; + } + + if (splittedVoiceName[2]?.length === 0) { + return false; + } + + const locales = splittedVoiceName.slice(0, 2); + + return locales.every((locale) => locale.length === 2); + }, + { + message: AvatarVideoValidationMessage.VOICE_NAME_INVALID, + path: ['voice'], + }, + ); + +export { renderAvatarVideo }; diff --git a/shared/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts b/shared/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..e497a8621 --- /dev/null +++ b/shared/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { renderAvatarVideo } from './render-avatar-video.validation-schema.js'; From ea5ab7d9130dc5dc205b3f5c8e32aba38fee76a2 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:39:38 +0300 Subject: [PATCH 07/22] OV-173: * api path --- shared/src/enums/api-path.enum.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/enums/api-path.enum.ts b/shared/src/enums/api-path.enum.ts index ea350bae1..03c77e649 100644 --- a/shared/src/enums/api-path.enum.ts +++ b/shared/src/enums/api-path.enum.ts @@ -6,6 +6,7 @@ const ApiPath = { VIDEOS: '/videos', CHAT: '/chat', SPEECH: '/speech', + AVATAR_VIDEO: '/avatar-video', } as const; export { ApiPath }; From f461b587d0ac213ed033be7f1f077be67508c619 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:42:18 +0300 Subject: [PATCH 08/22] OV-173: + enum --- .../enum/avatar-video-validation-message.enum.ts | 9 +++++++++ .../avatar-videos/enum/avatar-videos-api-path.enum.ts | 6 ++++++ shared/src/bundles/avatar-videos/enum/enums.ts | 2 ++ 3 files changed, 17 insertions(+) create mode 100644 shared/src/bundles/avatar-videos/enum/avatar-video-validation-message.enum.ts create mode 100644 shared/src/bundles/avatar-videos/enum/avatar-videos-api-path.enum.ts create mode 100644 shared/src/bundles/avatar-videos/enum/enums.ts diff --git a/shared/src/bundles/avatar-videos/enum/avatar-video-validation-message.enum.ts b/shared/src/bundles/avatar-videos/enum/avatar-video-validation-message.enum.ts new file mode 100644 index 000000000..b6b22d3bf --- /dev/null +++ b/shared/src/bundles/avatar-videos/enum/avatar-video-validation-message.enum.ts @@ -0,0 +1,9 @@ +const AvatarVideoValidationMessage = { + TEXT_REQUIRED: 'Text is required', + VOICE_NAME_REQUIRED: 'Voice name is required', + VOICE_NAME_INVALID: 'Please enter a valid voice name', + AVATAR_NAME_REQUIRED: 'Avatar name is required', + AVATAR_STYLE_REQUIRED: 'Avatar style is required', +} as const; + +export { AvatarVideoValidationMessage }; diff --git a/shared/src/bundles/avatar-videos/enum/avatar-videos-api-path.enum.ts b/shared/src/bundles/avatar-videos/enum/avatar-videos-api-path.enum.ts new file mode 100644 index 000000000..22d1f2dff --- /dev/null +++ b/shared/src/bundles/avatar-videos/enum/avatar-videos-api-path.enum.ts @@ -0,0 +1,6 @@ +const AvatarVideosApiPath = { + ROOT: '/', + ID: '/:id', +} as const; + +export { AvatarVideosApiPath }; diff --git a/shared/src/bundles/avatar-videos/enum/enums.ts b/shared/src/bundles/avatar-videos/enum/enums.ts new file mode 100644 index 000000000..d7991ccfc --- /dev/null +++ b/shared/src/bundles/avatar-videos/enum/enums.ts @@ -0,0 +1,2 @@ +export { AvatarVideoValidationMessage } from './avatar-video-validation-message.enum.js'; +export { AvatarVideosApiPath } from './avatar-videos-api-path.enum.js'; From a2bf371f4af3175b0abb1c5631f9ae6a8b3de8b4 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:44:19 +0300 Subject: [PATCH 09/22] OV-173: + export --- shared/src/bundles/avatar-videos/avatar-videos.ts | 12 ++++++++++++ shared/src/bundles/avatar-videos/types/types.ts | 8 ++++++++ shared/src/index.ts | 10 +++++++++- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 shared/src/bundles/avatar-videos/avatar-videos.ts create mode 100644 shared/src/bundles/avatar-videos/types/types.ts diff --git a/shared/src/bundles/avatar-videos/avatar-videos.ts b/shared/src/bundles/avatar-videos/avatar-videos.ts new file mode 100644 index 000000000..1aa47c573 --- /dev/null +++ b/shared/src/bundles/avatar-videos/avatar-videos.ts @@ -0,0 +1,12 @@ +export { AvatarVideosApiPath } from './enum/enums.js'; +export { + type AvatarConfig, + type GetAvatarVideoRequestDto, + type GetAvatarVideoResponseDto, + type InputKind, + type RenderAvatarResponseDto, + type RenderAvatarVideoRequestDto, + type VideoCodec, + type VideoFormat, +} from './types/types.js'; +export { renderAvatarVideo as renderAvatarVideoValidationSchema } from './validation-schemas/validation-schemas.js'; diff --git a/shared/src/bundles/avatar-videos/types/types.ts b/shared/src/bundles/avatar-videos/types/types.ts new file mode 100644 index 000000000..f9bfa702e --- /dev/null +++ b/shared/src/bundles/avatar-videos/types/types.ts @@ -0,0 +1,8 @@ +export { type AvatarConfig } from './avatar-config.type.js'; +export { type GetAvatarVideoRequestDto } from './get-avatar-video-request-dto.type.js'; +export { type GetAvatarVideoResponseDto } from './get-avatar-video-response-dto.type.js'; +export { type InputKind } from './input-kind.type.js'; +export { type RenderAvatarVideoRequestDto } from './render-avatar-request-dto.type.js'; +export { type RenderAvatarResponseDto } from './render-avatar-response-dto.type.js'; +export { type VideoCodec } from './video-codec.type.js'; +export { type VideoFormat } from './video-format.type.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index f7e4e31cd..ef4024c30 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -1,8 +1,16 @@ export { AuthApiPath } from './bundles/auth/auth.js'; export { + type AvatarConfig, + type GetAvatarVideoRequestDto, + type GetAvatarVideoResponseDto, + type InputKind, + type RenderAvatarResponseDto, + type RenderAvatarVideoRequestDto, type VideoCodec, type VideoFormat, -} from './bundles/avatar-video/avatar-video.js'; + AvatarVideosApiPath, + renderAvatarVideoValidationSchema, +} from './bundles/avatar-videos/avatar-videos.js'; export { type AvatarGetAllResponseDto, type AvatarGetOneRequestDto, From 09e587cb051560325a83e9b7fd34038ace3423ef Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:45:39 +0300 Subject: [PATCH 10/22] OV-173: + helper --- .../avatar-videos/avatar-videos.service.ts | 82 +++++++++++++++++++ .../src/bundles/avatar-videos/enums/enums.ts | 1 + .../helpers/get-file-name.helper.ts | 5 ++ .../bundles/avatar-videos/helpers/helpers.ts | 1 + 4 files changed, 89 insertions(+) create mode 100644 backend/src/bundles/avatar-videos/avatar-videos.service.ts create mode 100644 backend/src/bundles/avatar-videos/enums/enums.ts create mode 100644 backend/src/bundles/avatar-videos/helpers/get-file-name.helper.ts create mode 100644 backend/src/bundles/avatar-videos/helpers/helpers.ts diff --git a/backend/src/bundles/avatar-videos/avatar-videos.service.ts b/backend/src/bundles/avatar-videos/avatar-videos.service.ts new file mode 100644 index 000000000..5363721ad --- /dev/null +++ b/backend/src/bundles/avatar-videos/avatar-videos.service.ts @@ -0,0 +1,82 @@ +import { type AzureAIService } from '~/common/services/azure-ai/azure-ai.service.js'; +import { type FileService } from '~/common/services/file/file.service.js'; + +import { getFileName } from './helpers/helpers.js'; +import { + type GetAvatarVideoRequestDto, + type GetAvatarVideoResponseDto, + type RenderAvatarResponseDto, + type RenderAvatarVideoRequestDto, +} from './types/types.js'; + +class AvatarVideoService { + private azureAIService: AzureAIService; + private fileService: FileService; + + public constructor( + azureAIService: AzureAIService, + fileService: FileService, + ) { + this.azureAIService = azureAIService; + this.fileService = fileService; + } + + public async renderAvatarVideo( + payload: RenderAvatarVideoRequestDto, + ): Promise { + const response = await this.azureAIService.renderAvatarVideo({ + id: Date.now().toString(), + payload, + }); + + this.checkAvatarProcessing(response.id); + + return response; + } + + public getAvatarVideo( + payload: GetAvatarVideoRequestDto, + ): Promise { + return this.azureAIService.getAvatarVideo(payload.id); + } + + public async saveAvatarVideo(url: string, id: string): Promise { + const buffer = await this.azureAIService.getAvatarVideoBuffer(url); + + const fileName = getFileName(id); + + await this.fileService.uploadFile(buffer, fileName); + return this.fileService.getCloudFrontFileUrl(fileName); + } + + public removeAvatarVideo(id: string): Promise { + return this.azureAIService.removeAvatarVideo(id); + } + + public checkAvatarProcessing(id: string): void { + const interval = setInterval((): void => { + this.azureAIService + .getAvatarVideo(id) + .then((response) => { + if (response.status === 'Succeeded') { + this.saveAvatarVideo(response.outputs.result, id) + .then(() => { + // TODO: NOTIFY USER + }) + .catch(() => {}) + .finally(() => { + clearInterval(interval); + }); + } else if (response.status === 'Failed') { + // TODO: NOTIFY USER + clearInterval(interval); + } + }) + .catch(() => { + clearInterval(interval); + }); + }, 4000); + } +} + +export { AvatarVideoService }; diff --git a/backend/src/bundles/avatar-videos/enums/enums.ts b/backend/src/bundles/avatar-videos/enums/enums.ts new file mode 100644 index 000000000..8f47f5668 --- /dev/null +++ b/backend/src/bundles/avatar-videos/enums/enums.ts @@ -0,0 +1 @@ +export { AvatarVideosApiPath } from 'shared'; diff --git a/backend/src/bundles/avatar-videos/helpers/get-file-name.helper.ts b/backend/src/bundles/avatar-videos/helpers/get-file-name.helper.ts new file mode 100644 index 000000000..46d4d6b2d --- /dev/null +++ b/backend/src/bundles/avatar-videos/helpers/get-file-name.helper.ts @@ -0,0 +1,5 @@ +const getFileName = (id: string): string => { + return `${id}.webm`; +}; + +export { getFileName }; diff --git a/backend/src/bundles/avatar-videos/helpers/helpers.ts b/backend/src/bundles/avatar-videos/helpers/helpers.ts new file mode 100644 index 000000000..572a555c7 --- /dev/null +++ b/backend/src/bundles/avatar-videos/helpers/helpers.ts @@ -0,0 +1 @@ +export { getFileName } from './get-file-name.helper.js'; From abea102eef72e504470aa13704e91e952d03bc89 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:46:47 +0300 Subject: [PATCH 11/22] OV-173: * azure-service --- .../services/azure-ai/azure-ai.service.ts | 52 +++++++++++++++++-- backend/src/common/services/services.ts | 9 +++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/backend/src/common/services/azure-ai/azure-ai.service.ts b/backend/src/common/services/azure-ai/azure-ai.service.ts index 8dc76a817..9373a2850 100644 --- a/backend/src/common/services/azure-ai/azure-ai.service.ts +++ b/backend/src/common/services/azure-ai/azure-ai.service.ts @@ -10,23 +10,40 @@ import { import { type BaseConfig } from '~/common/config/base-config.package.js'; import { type FileService } from '../file/file.service.js'; +import { + type AvatarVideoApi, + type GetAvatarVideoResponseDto, + type RenderAvatarVideoApiResponseDto, + type RenderAvatarVideoArgument, +} from './apis/avatar-video/avatar-video.js'; import { type TextToSpeechApi } from './apis/text-to-speech-api.js'; +import { getAvatarConfig } from './helpers/helpers.js'; import { type AzureGetVoicesResponseDto } from './types/types.js'; +type Constructor = { + config: BaseConfig; + fileService: FileService; + textToSpeechApi: TextToSpeechApi; + avatarVideoApi: AvatarVideoApi; +}; + class AzureAIService { private fileService: FileService; private textToSpeechApi: TextToSpeechApi; + private avatarVideoApi: AvatarVideoApi; private subscriptionKey: string; private serviceRegion: string; - public constructor( - config: BaseConfig, - fileService: FileService, - textToSpeechApi: TextToSpeechApi, - ) { + public constructor({ + avatarVideoApi, + config, + fileService, + textToSpeechApi, + }: Constructor) { this.fileService = fileService; this.textToSpeechApi = textToSpeechApi; + this.avatarVideoApi = avatarVideoApi; this.subscriptionKey = config.ENV.AZURE.SUBSCRIPTION_KEY; this.serviceRegion = config.ENV.AZURE.SERVICE_REGION; @@ -125,6 +142,31 @@ class AzureAIService { await fs.unlink(audioFileName); } } + + public async renderAvatarVideo( + payload: RenderAvatarVideoArgument, + ): Promise { + const { id, payload: avatarPayload } = payload; + const avatarConfig = getAvatarConfig(avatarPayload); + return await this.avatarVideoApi.renderAvatarVideo({ + id, + payload: avatarConfig, + }); + } + + public async getAvatarVideo( + id: string, + ): Promise { + return await this.avatarVideoApi.getAvatarVideo(id); + } + + public async getAvatarVideoBuffer(url: string): Promise { + return await this.avatarVideoApi.getAvatarVideoBuffer(url); + } + + public async removeAvatarVideo(id: string): Promise { + return await this.avatarVideoApi.deleteAvatarVideo(id); + } } export { AzureAIService }; diff --git a/backend/src/common/services/services.ts b/backend/src/common/services/services.ts index 5bb6a3b00..725db6e52 100644 --- a/backend/src/common/services/services.ts +++ b/backend/src/common/services/services.ts @@ -1,6 +1,6 @@ import { config } from '~/common/config/config.js'; -import { textToSpeechApi } from './azure-ai/apis/apis.js'; +import { avatarVideoApi, textToSpeechApi } from './azure-ai/apis/apis.js'; import { AzureAIService } from './azure-ai/azure-ai.service.js'; import { CryptService } from './crypt/crypt.service.js'; import { FileService } from './file/file.service.js'; @@ -10,7 +10,12 @@ import { TokenService } from './token/token.services.js'; const openAIService = new OpenAIService(config); const cryptService = new CryptService(); const fileService = new FileService(config); -const azureAIService = new AzureAIService(config, fileService, textToSpeechApi); +const azureAIService = new AzureAIService({ + config, + fileService, + textToSpeechApi, + avatarVideoApi, +}); const secretKey = config.ENV.TOKEN.SECRET_KEY; const expirationTime = config.ENV.TOKEN.EXPIRATION_TIME; From f7829a58beaf99b0d9ac4ca6406c81285d61bb23 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 12:48:09 +0300 Subject: [PATCH 12/22] OV-173: * avatar-video controller --- .../avatar-videos/avatar-videos.controller.ts | 80 +++++++++++++++++++ .../bundles/avatar-videos/avatar-videos.ts | 14 ++++ .../validation-schemas/validation-schemas.ts | 1 + .../server-application/server-application.ts | 2 + 4 files changed, 97 insertions(+) create mode 100644 backend/src/bundles/avatar-videos/avatar-videos.controller.ts create mode 100644 backend/src/bundles/avatar-videos/avatar-videos.ts create mode 100644 backend/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts diff --git a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts new file mode 100644 index 000000000..ca4b5c6a2 --- /dev/null +++ b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts @@ -0,0 +1,80 @@ +import { ApiPath } from 'shared'; + +import { + type ApiHandlerOptions, + type ApiHandlerResponse, +} from '~/common/controller/controller.js'; +import { BaseController } from '~/common/controller/controller.js'; +import { HttpCode, HTTPMethod } from '~/common/http/http.js'; +import { type Logger } from '~/common/logger/logger.js'; + +import { type AvatarVideoService } from './avatar-videos.service.js'; +import { AvatarVideosApiPath } from './enums/enums.js'; +import { + type GetAvatarVideoRequestDto, + type RenderAvatarVideoRequestDto, +} from './types/types.js'; +import { renderAvatarVideoValidationSchema } from './validation-schemas/validation-schemas.js'; + +class AvatarVideoController extends BaseController { + private avatarVideoService: AvatarVideoService; + + public constructor(logger: Logger, avatarVideoService: AvatarVideoService) { + super(logger, ApiPath.AVATAR_VIDEO); + + this.avatarVideoService = avatarVideoService; + + this.addRoute({ + path: AvatarVideosApiPath.ID, + method: HTTPMethod.GET, + handler: (options) => + this.getAvatarVideo( + options as ApiHandlerOptions<{ + params: GetAvatarVideoRequestDto; + }>, + ), + }); + + this.addRoute({ + path: AvatarVideosApiPath.ROOT, + method: HTTPMethod.POST, + validation: { + body: renderAvatarVideoValidationSchema, + }, + handler: (options) => + this.renderAvatarVideo( + options as ApiHandlerOptions<{ + body: RenderAvatarVideoRequestDto; + }>, + ), + }); + } + + private async getAvatarVideo( + options: ApiHandlerOptions<{ + params: GetAvatarVideoRequestDto; + }>, + ): Promise { + return { + payload: await this.avatarVideoService.getAvatarVideo({ + id: options.params.id, + }), + status: HttpCode.OK, + }; + } + + private async renderAvatarVideo( + options: ApiHandlerOptions<{ + body: RenderAvatarVideoRequestDto; + }>, + ): Promise { + return { + payload: await this.avatarVideoService.renderAvatarVideo( + options.body, + ), + status: HttpCode.CREATED, + }; + } +} + +export { AvatarVideoController }; diff --git a/backend/src/bundles/avatar-videos/avatar-videos.ts b/backend/src/bundles/avatar-videos/avatar-videos.ts new file mode 100644 index 000000000..0a1b1e130 --- /dev/null +++ b/backend/src/bundles/avatar-videos/avatar-videos.ts @@ -0,0 +1,14 @@ +import { logger } from '~/common/logger/logger.js'; +import { azureAIService, fileService } from '~/common/services/services.js'; + +import { AvatarVideoController } from './avatar-videos.controller.js'; +import { AvatarVideoService } from './avatar-videos.service.js'; + +const avatarVideoService = new AvatarVideoService(azureAIService, fileService); + +const avatarVideoController = new AvatarVideoController( + logger, + avatarVideoService, +); + +export { avatarVideoController }; diff --git a/backend/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts b/backend/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..6c5804f7d --- /dev/null +++ b/backend/src/bundles/avatar-videos/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { renderAvatarVideoValidationSchema } from 'shared'; diff --git a/backend/src/common/server-application/server-application.ts b/backend/src/common/server-application/server-application.ts index 532d92a0c..68438a60e 100644 --- a/backend/src/common/server-application/server-application.ts +++ b/backend/src/common/server-application/server-application.ts @@ -1,4 +1,5 @@ import { authController } from '~/bundles/auth/auth.js'; +import { avatarVideoController } from '~/bundles/avatar-videos/avatar-videos.js'; import { avatarController } from '~/bundles/avatars/avatars.js'; import { chatController } from '~/bundles/chat/chat.js'; import { speechController } from '~/bundles/speech/speech.js'; @@ -20,6 +21,7 @@ const apiV1 = new BaseServerAppApi( ...videoController.routes, ...chatController.routes, ...speechController.routes, + ...avatarVideoController.routes, ); const serverApp = new BaseServerApp({ From dd574535d23819a659b2c11d463a39576b105f03 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 14:17:42 +0300 Subject: [PATCH 13/22] OV-173: + enum --- backend/src/bundles/avatar-videos/enums/enums.ts | 2 ++ .../enums/generate-avatar-response-status.enum.ts | 6 ++++++ .../avatar-videos/enums/render-video-error-message.enum.ts | 5 +++++ 3 files changed, 13 insertions(+) create mode 100644 backend/src/bundles/avatar-videos/enums/generate-avatar-response-status.enum.ts create mode 100644 backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts diff --git a/backend/src/bundles/avatar-videos/enums/enums.ts b/backend/src/bundles/avatar-videos/enums/enums.ts index 8f47f5668..0dc846e06 100644 --- a/backend/src/bundles/avatar-videos/enums/enums.ts +++ b/backend/src/bundles/avatar-videos/enums/enums.ts @@ -1 +1,3 @@ +export { GenerateAvatarResponseStatus } from './generate-avatar-response-status.enum.js'; +export { RenderVideoErrorMessage } from './render-video-error-message.enum.js'; export { AvatarVideosApiPath } from 'shared'; diff --git a/backend/src/bundles/avatar-videos/enums/generate-avatar-response-status.enum.ts b/backend/src/bundles/avatar-videos/enums/generate-avatar-response-status.enum.ts new file mode 100644 index 000000000..0d05f69bc --- /dev/null +++ b/backend/src/bundles/avatar-videos/enums/generate-avatar-response-status.enum.ts @@ -0,0 +1,6 @@ +const GenerateAvatarResponseStatus = { + SUCCEEDED: 'Succeeded', + FAILED: 'Failed', +} as const; + +export { GenerateAvatarResponseStatus }; diff --git a/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts b/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts new file mode 100644 index 000000000..615d8468f --- /dev/null +++ b/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts @@ -0,0 +1,5 @@ +const RenderVideoErrorMessage = { + NOT_FOUND: 'Video not found', +} as const; + +export { RenderVideoErrorMessage }; From 834998af00e8b480e197edd77e7067b99adf580b Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 14:19:03 +0300 Subject: [PATCH 14/22] OV-173: * types --- .../apis/avatar-video/avatar-video-api.ts | 6 ++-- .../apis/avatar-video/avatar-video.ts | 2 +- .../types/get-avatar-video-api-dto.type.ts | 36 +++++++++++++++++++ .../apis/avatar-video/libs/types/types.ts | 2 +- .../services/azure-ai/azure-ai.service.ts | 4 +-- .../get-avatar-video-response-dto.type.ts | 34 +----------------- 6 files changed, 44 insertions(+), 40 deletions(-) create mode 100644 backend/src/common/services/azure-ai/apis/avatar-video/libs/types/get-avatar-video-api-dto.type.ts diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts index a0628c127..d1da8551a 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video-api.ts @@ -6,7 +6,7 @@ import { BaseHttpApi } from '~/common/http/http.js'; import { AvatarApiPath } from './libs/enums/enums.js'; import { - type GetAvatarVideoResponseDto, + type GetAvatarVideoResponseApiDto, type RenderAvatarVideoApiArgument, type RenderAvatarVideoApiResponseDto, } from './libs/types/types.js'; @@ -23,7 +23,7 @@ class AvatarVideoApi extends BaseHttpApi { public async getAvatarVideo( id: string, - ): Promise { + ): Promise { const response = await this.load( this.getFullEndpoint( `${AvatarApiPath.BATCHSYNTHESES}/${id}?api-version=2024-08-01`, @@ -41,7 +41,7 @@ class AvatarVideoApi extends BaseHttpApi { }, ); - return await response.json(); + return await response.json(); } public async deleteAvatarVideo(id: string): Promise { diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts index 6c4af971f..c08e3fa0b 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/avatar-video.ts @@ -12,7 +12,7 @@ export { avatarVideoApi }; export { AvatarVideoApi } from './avatar-video-api.js'; export { AvatarApiPath } from './libs/enums/enums.js'; export { - type GetAvatarVideoResponseDto, + type GetAvatarVideoResponseApiDto, type RenderAvatarVideoApiRequestDto, type RenderAvatarVideoApiResponseDto, type RenderAvatarVideoArgument, diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/get-avatar-video-api-dto.type.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/get-avatar-video-api-dto.type.ts new file mode 100644 index 000000000..8aae433de --- /dev/null +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/get-avatar-video-api-dto.type.ts @@ -0,0 +1,36 @@ +import { type InputKind, type VideoCodec, type VideoFormat } from './types.js'; + +type GetAvatarVideoResponseApiDto = { + id: string; + internalId: string; + status: string; + createdDateTime: string; + lastActionDateTime: string; + inputKind: InputKind; + properties: { + timeToLiveInHours: number; + sizeInBytes: number; + durationInMilliseconds: number; + succeededCount: number; + failedCount: number; + billingDetails: { + neuralCharacters: number; + talkingAvatarDurationSeconds: number; + }; + }; + avatarConfig: { + talkingAvatarCharacter: string; + talkingAvatarStyle: string; + videoFormat: VideoFormat; + videoCodec: VideoCodec; + subtitleType: string; + bitrateKbps: number; + customized: boolean; + }; + outputs: { + result: string; + summary: string; + }; +}; + +export { type GetAvatarVideoResponseApiDto }; diff --git a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts index cb2cd3baf..ec58c6ff1 100644 --- a/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts +++ b/backend/src/common/services/azure-ai/apis/avatar-video/libs/types/types.ts @@ -1,8 +1,8 @@ +export { type GetAvatarVideoResponseApiDto } from './get-avatar-video-api-dto.type.js'; export { type RenderAvatarVideoApiArgument } from './render-avatar-video-api-argument.type.js'; export { type RenderAvatarVideoApiRequestDto } from './render-avatar-video-api-request-dto.type.js'; export { type RenderAvatarVideoApiResponseDto } from './render-avatar-video-api-response-dto.type.js'; export { type RenderAvatarVideoArgument } from './render-avatar-video-arguments.type.js'; -export { type GetAvatarVideoResponseDto } from 'shared'; export { type AvatarConfig, type InputKind, diff --git a/backend/src/common/services/azure-ai/azure-ai.service.ts b/backend/src/common/services/azure-ai/azure-ai.service.ts index ba32d25e4..7cffa5cc9 100644 --- a/backend/src/common/services/azure-ai/azure-ai.service.ts +++ b/backend/src/common/services/azure-ai/azure-ai.service.ts @@ -15,10 +15,10 @@ import { type BaseConfig } from '~/common/config/base-config.package.js'; import { type FileService } from '../file/file.service.js'; import { type AvatarVideoApi, - type GetAvatarVideoResponseDto, type RenderAvatarVideoApiResponseDto, type RenderAvatarVideoArgument, } from './apis/avatar-video/avatar-video.js'; +import { type GetAvatarVideoResponseApiDto } from './apis/avatar-video/libs/types/types.js'; import { type TextToSpeechApi } from './apis/text-to-speech/text-to-speech-api.js'; import { DEFAULT_LANGUAGE } from './constants/constants.js'; import { getAvatarConfig } from './helpers/helpers.js'; @@ -139,7 +139,7 @@ class AzureAIService { public async getAvatarVideo( id: string, - ): Promise { + ): Promise { return await this.avatarVideoApi.getAvatarVideo(id); } diff --git a/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts b/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts index 0f1f855cd..36e3cc173 100644 --- a/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts +++ b/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts @@ -1,37 +1,5 @@ -import { type InputKind } from './input-kind.type.js'; -import { type VideoCodec, type VideoFormat } from './types.js'; - type GetAvatarVideoResponseDto = { - id: string; - internalId: string; - status: string; - createdDateTime: string; - lastActionDateTime: string; - inputKind: InputKind; - properties: { - timeToLiveInHours: number; - sizeInBytes: number; - durationInMilliseconds: number; - succeededCount: number; - failedCount: number; - billingDetails: { - neuralCharacters: number; - talkingAvatarDurationSeconds: number; - }; - }; - avatarConfig: { - talkingAvatarCharacter: string; - talkingAvatarStyle: string; - videoFormat: VideoFormat; - videoCodec: VideoCodec; - subtitleType: string; - bitrateKbps: number; - customized: boolean; - }; - outputs: { - result: string; - summary: string; - }; + url: string; }; export { type GetAvatarVideoResponseDto }; From ad5efb4aadcd64d35fc227e1269d2908709ade04 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 14:23:20 +0300 Subject: [PATCH 15/22] OV-173: * avatar-video service --- .../avatar-videos/avatar-videos.service.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/backend/src/bundles/avatar-videos/avatar-videos.service.ts b/backend/src/bundles/avatar-videos/avatar-videos.service.ts index 5363721ad..71dfa8f55 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.service.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.service.ts @@ -1,6 +1,12 @@ +import { HttpCode, HttpError } from 'shared'; + import { type AzureAIService } from '~/common/services/azure-ai/azure-ai.service.js'; import { type FileService } from '~/common/services/file/file.service.js'; +import { + GenerateAvatarResponseStatus, + RenderVideoErrorMessage, +} from './enums/enums.js'; import { getFileName } from './helpers/helpers.js'; import { type GetAvatarVideoRequestDto, @@ -34,10 +40,18 @@ class AvatarVideoService { return response; } - public getAvatarVideo( + public async getAvatarVideo( payload: GetAvatarVideoRequestDto, ): Promise { - return this.azureAIService.getAvatarVideo(payload.id); + const response = await this.azureAIService.getAvatarVideo(payload.id); + + if (!response?.outputs?.result) { + throw new HttpError({ + message: RenderVideoErrorMessage.NOT_FOUND, + status: HttpCode.NOT_FOUND, + }); + } + return { url: response?.outputs?.result }; } public async saveAvatarVideo(url: string, id: string): Promise { @@ -58,7 +72,10 @@ class AvatarVideoService { this.azureAIService .getAvatarVideo(id) .then((response) => { - if (response.status === 'Succeeded') { + if ( + response.status === + GenerateAvatarResponseStatus.SUCCEEDED + ) { this.saveAvatarVideo(response.outputs.result, id) .then(() => { // TODO: NOTIFY USER @@ -67,7 +84,9 @@ class AvatarVideoService { .finally(() => { clearInterval(interval); }); - } else if (response.status === 'Failed') { + } else if ( + response.status === GenerateAvatarResponseStatus.FAILED + ) { // TODO: NOTIFY USER clearInterval(interval); } From ea0c2f273a527a7364f6b69e04af07b31e2c6904 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 9 Sep 2024 14:35:27 +0300 Subject: [PATCH 16/22] OV-173: + swagger --- .../avatar-videos/avatar-videos.controller.ts | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts index ca4b5c6a2..7bb307607 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts @@ -50,6 +50,24 @@ class AvatarVideoController extends BaseController { }); } + /** + * @swagger + * /avatar-video/:id: + * get: + * description: Get video url + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * url: + * type: string + */ private async getAvatarVideo( options: ApiHandlerOptions<{ params: GetAvatarVideoRequestDto; @@ -63,6 +81,41 @@ class AvatarVideoController extends BaseController { }; } + /** + * @swagger + * /avatar-video: + * post: + * description: Generate video from text + * security: + * - bearerAuth: [] + * requestBody: + * description: Data for video generation + * required: true + * content: + * application/json: + * schema: + * type: object + * required: [text, voice, avatarName, avatarStyle] + * properties: + * text: + * type: string + * voice: + * type: string + * avatarName: + * type: string + * avatarStyle: + * type: string + * responses: + * 201: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * id: + * type: string + */ private async renderAvatarVideo( options: ApiHandlerOptions<{ body: RenderAvatarVideoRequestDto; From d93f181074aacd775ced147689a21118f201bb3e Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 10 Sep 2024 09:55:27 +0300 Subject: [PATCH 17/22] OV-173: * export --- backend/src/bundles/videos/videos.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/bundles/videos/videos.ts b/backend/src/bundles/videos/videos.ts index aa892cca4..49fe1edb6 100644 --- a/backend/src/bundles/videos/videos.ts +++ b/backend/src/bundles/videos/videos.ts @@ -9,4 +9,4 @@ const videoRepository = new VideoRepository(VideoModel); const videoService = new VideoService(videoRepository); const videoController = new VideoController(logger, videoService); -export { videoController }; +export { videoController, videoService }; From 94fb64a68d12248ca388e4bd738301a1191aa944 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 10 Sep 2024 09:56:49 +0300 Subject: [PATCH 18/22] OV-173: * error message --- .../avatar-videos/enums/render-video-error-message.enum.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts b/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts index 615d8468f..08ea290c9 100644 --- a/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts +++ b/backend/src/bundles/avatar-videos/enums/render-video-error-message.enum.ts @@ -1,5 +1,6 @@ const RenderVideoErrorMessage = { NOT_FOUND: 'Video not found', + NOT_SAVED: 'Video was not saved', } as const; export { RenderVideoErrorMessage }; From 32294674ba1767a8728e790845c3bee6710aff44 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 10 Sep 2024 09:57:59 +0300 Subject: [PATCH 19/22] OV-173: * avatar-video-service --- .../avatar-videos/avatar-videos.service.ts | 81 +++++++++++++++---- .../bundles/avatar-videos/avatar-videos.ts | 7 +- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/backend/src/bundles/avatar-videos/avatar-videos.service.ts b/backend/src/bundles/avatar-videos/avatar-videos.service.ts index 71dfa8f55..0ae0ddb60 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.service.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.service.ts @@ -3,6 +3,7 @@ import { HttpCode, HttpError } from 'shared'; import { type AzureAIService } from '~/common/services/azure-ai/azure-ai.service.js'; import { type FileService } from '~/common/services/file/file.service.js'; +import { type VideoService } from '../videos/video.service.js'; import { GenerateAvatarResponseStatus, RenderVideoErrorMessage, @@ -15,29 +16,25 @@ import { type RenderAvatarVideoRequestDto, } from './types/types.js'; +type HandleRenderVideoArguments = { + id: string; + userId: string; + url: string; +}; + class AvatarVideoService { private azureAIService: AzureAIService; private fileService: FileService; + private videoService: VideoService; public constructor( azureAIService: AzureAIService, fileService: FileService, + videoService: VideoService, ) { this.azureAIService = azureAIService; this.fileService = fileService; - } - - public async renderAvatarVideo( - payload: RenderAvatarVideoRequestDto, - ): Promise { - const response = await this.azureAIService.renderAvatarVideo({ - id: Date.now().toString(), - payload, - }); - - this.checkAvatarProcessing(response.id); - - return response; + this.videoService = videoService; } public async getAvatarVideo( @@ -67,7 +64,21 @@ class AvatarVideoService { return this.azureAIService.removeAvatarVideo(id); } - public checkAvatarProcessing(id: string): void { + public async renderAvatarVideo( + payload: RenderAvatarVideoRequestDto & { userId: string }, + ): Promise { + const { userId, ...avatarConfig } = payload; + const response = await this.azureAIService.renderAvatarVideo({ + id: Date.now().toString(), + payload: avatarConfig, + }); + + this.checkAvatarProcessing(response.id, userId); + + return response; + } + + public checkAvatarProcessing(id: string, userId: string): void { const interval = setInterval((): void => { this.azureAIService .getAvatarVideo(id) @@ -76,11 +87,20 @@ class AvatarVideoService { response.status === GenerateAvatarResponseStatus.SUCCEEDED ) { - this.saveAvatarVideo(response.outputs.result, id) + this.handleSuccessfulAvatarGeneration({ + id, + userId, + url: response.outputs.result, + }) .then(() => { // TODO: NOTIFY USER }) - .catch(() => {}) + .catch((error) => { + throw new HttpError({ + message: error.message, + status: error.status, + }); + }) .finally(() => { clearInterval(interval); }); @@ -91,11 +111,38 @@ class AvatarVideoService { clearInterval(interval); } }) - .catch(() => { + .catch((error) => { clearInterval(interval); + throw new HttpError({ + message: error.message, + status: error.status, + }); }); }, 4000); } + + private async handleSuccessfulAvatarGeneration({ + id, + url, + userId, + }: HandleRenderVideoArguments): Promise { + const savedUrl = await this.saveAvatarVideo(url, id); + + const videoData = await this.videoService.create({ + name: getFileName(id), + url: savedUrl, + userId, + }); + + if (!videoData) { + throw new HttpError({ + message: RenderVideoErrorMessage.NOT_SAVED, + status: HttpCode.BAD_REQUEST, + }); + } + + await this.azureAIService.removeAvatarVideo(id); + } } export { AvatarVideoService }; diff --git a/backend/src/bundles/avatar-videos/avatar-videos.ts b/backend/src/bundles/avatar-videos/avatar-videos.ts index 0a1b1e130..85a13556b 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.ts @@ -1,10 +1,15 @@ import { logger } from '~/common/logger/logger.js'; import { azureAIService, fileService } from '~/common/services/services.js'; +import { videoService } from '../videos/videos.js'; import { AvatarVideoController } from './avatar-videos.controller.js'; import { AvatarVideoService } from './avatar-videos.service.js'; -const avatarVideoService = new AvatarVideoService(azureAIService, fileService); +const avatarVideoService = new AvatarVideoService( + azureAIService, + fileService, + videoService, +); const avatarVideoController = new AvatarVideoController( logger, From 5f4c754b57c763a93c036fc29cecfe7af1647654 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 10 Sep 2024 09:59:21 +0300 Subject: [PATCH 20/22] OV-173: * avatar comtroller --- .../bundles/avatar-videos/avatar-videos.controller.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts index 7bb307607..624449582 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts @@ -1,4 +1,4 @@ -import { ApiPath } from 'shared'; +import { type UserGetCurrentResponseDto, ApiPath } from 'shared'; import { type ApiHandlerOptions, @@ -122,9 +122,10 @@ class AvatarVideoController extends BaseController { }>, ): Promise { return { - payload: await this.avatarVideoService.renderAvatarVideo( - options.body, - ), + payload: await this.avatarVideoService.renderAvatarVideo({ + ...options.body, + userId: (options.user as UserGetCurrentResponseDto).id, + }), status: HttpCode.CREATED, }; } From 6b3bc3e8f8eaa719b5e38909172a49bfd6446e83 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 10 Sep 2024 12:07:49 +0300 Subject: [PATCH 21/22] OV-173: - types --- .../avatar-videos/avatar-videos.controller.ts | 47 +------------------ .../avatar-videos/avatar-videos.service.ts | 23 ++------- .../src/bundles/avatar-videos/types/types.ts | 2 - .../bundles/avatar-videos/avatar-videos.ts | 2 - .../get-avatar-video-request-dto.type.ts | 5 -- .../get-avatar-video-response-dto.type.ts | 5 -- .../src/bundles/avatar-videos/types/types.ts | 2 - shared/src/index.ts | 2 - 8 files changed, 5 insertions(+), 83 deletions(-) delete mode 100644 shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts delete mode 100644 shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts diff --git a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts index 624449582..7acbeca20 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.controller.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.controller.ts @@ -10,10 +10,7 @@ import { type Logger } from '~/common/logger/logger.js'; import { type AvatarVideoService } from './avatar-videos.service.js'; import { AvatarVideosApiPath } from './enums/enums.js'; -import { - type GetAvatarVideoRequestDto, - type RenderAvatarVideoRequestDto, -} from './types/types.js'; +import { type RenderAvatarVideoRequestDto } from './types/types.js'; import { renderAvatarVideoValidationSchema } from './validation-schemas/validation-schemas.js'; class AvatarVideoController extends BaseController { @@ -24,17 +21,6 @@ class AvatarVideoController extends BaseController { this.avatarVideoService = avatarVideoService; - this.addRoute({ - path: AvatarVideosApiPath.ID, - method: HTTPMethod.GET, - handler: (options) => - this.getAvatarVideo( - options as ApiHandlerOptions<{ - params: GetAvatarVideoRequestDto; - }>, - ), - }); - this.addRoute({ path: AvatarVideosApiPath.ROOT, method: HTTPMethod.POST, @@ -50,37 +36,6 @@ class AvatarVideoController extends BaseController { }); } - /** - * @swagger - * /avatar-video/:id: - * get: - * description: Get video url - * security: - * - bearerAuth: [] - * responses: - * 200: - * description: Successful operation - * content: - * application/json: - * schema: - * type: object - * properties: - * url: - * type: string - */ - private async getAvatarVideo( - options: ApiHandlerOptions<{ - params: GetAvatarVideoRequestDto; - }>, - ): Promise { - return { - payload: await this.avatarVideoService.getAvatarVideo({ - id: options.params.id, - }), - status: HttpCode.OK, - }; - } - /** * @swagger * /avatar-video: diff --git a/backend/src/bundles/avatar-videos/avatar-videos.service.ts b/backend/src/bundles/avatar-videos/avatar-videos.service.ts index 0ae0ddb60..2fc978cac 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.service.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.service.ts @@ -1,4 +1,5 @@ import { HttpCode, HttpError } from 'shared'; +import { v4 as uuidv4 } from 'uuid'; import { type AzureAIService } from '~/common/services/azure-ai/azure-ai.service.js'; import { type FileService } from '~/common/services/file/file.service.js'; @@ -10,8 +11,6 @@ import { } from './enums/enums.js'; import { getFileName } from './helpers/helpers.js'; import { - type GetAvatarVideoRequestDto, - type GetAvatarVideoResponseDto, type RenderAvatarResponseDto, type RenderAvatarVideoRequestDto, } from './types/types.js'; @@ -37,21 +36,7 @@ class AvatarVideoService { this.videoService = videoService; } - public async getAvatarVideo( - payload: GetAvatarVideoRequestDto, - ): Promise { - const response = await this.azureAIService.getAvatarVideo(payload.id); - - if (!response?.outputs?.result) { - throw new HttpError({ - message: RenderVideoErrorMessage.NOT_FOUND, - status: HttpCode.NOT_FOUND, - }); - } - return { url: response?.outputs?.result }; - } - - public async saveAvatarVideo(url: string, id: string): Promise { + private async saveAvatarVideo(url: string, id: string): Promise { const buffer = await this.azureAIService.getAvatarVideoBuffer(url); const fileName = getFileName(id); @@ -69,7 +54,7 @@ class AvatarVideoService { ): Promise { const { userId, ...avatarConfig } = payload; const response = await this.azureAIService.renderAvatarVideo({ - id: Date.now().toString(), + id: uuidv4(), payload: avatarConfig, }); @@ -78,7 +63,7 @@ class AvatarVideoService { return response; } - public checkAvatarProcessing(id: string, userId: string): void { + private checkAvatarProcessing(id: string, userId: string): void { const interval = setInterval((): void => { this.azureAIService .getAvatarVideo(id) diff --git a/backend/src/bundles/avatar-videos/types/types.ts b/backend/src/bundles/avatar-videos/types/types.ts index cdbb67a6e..3ae9bba76 100644 --- a/backend/src/bundles/avatar-videos/types/types.ts +++ b/backend/src/bundles/avatar-videos/types/types.ts @@ -1,6 +1,4 @@ export { - type GetAvatarVideoRequestDto, - type GetAvatarVideoResponseDto, type RenderAvatarResponseDto, type RenderAvatarVideoRequestDto, } from 'shared'; diff --git a/shared/src/bundles/avatar-videos/avatar-videos.ts b/shared/src/bundles/avatar-videos/avatar-videos.ts index 1aa47c573..0ee74c140 100644 --- a/shared/src/bundles/avatar-videos/avatar-videos.ts +++ b/shared/src/bundles/avatar-videos/avatar-videos.ts @@ -1,8 +1,6 @@ export { AvatarVideosApiPath } from './enum/enums.js'; export { type AvatarConfig, - type GetAvatarVideoRequestDto, - type GetAvatarVideoResponseDto, type InputKind, type RenderAvatarResponseDto, type RenderAvatarVideoRequestDto, diff --git a/shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts b/shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts deleted file mode 100644 index 725cd1793..000000000 --- a/shared/src/bundles/avatar-videos/types/get-avatar-video-request-dto.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type GetAvatarVideoRequestDto = { - id: string; -}; - -export { type GetAvatarVideoRequestDto }; diff --git a/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts b/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts deleted file mode 100644 index 36e3cc173..000000000 --- a/shared/src/bundles/avatar-videos/types/get-avatar-video-response-dto.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type GetAvatarVideoResponseDto = { - url: string; -}; - -export { type GetAvatarVideoResponseDto }; diff --git a/shared/src/bundles/avatar-videos/types/types.ts b/shared/src/bundles/avatar-videos/types/types.ts index f9bfa702e..c849c25b1 100644 --- a/shared/src/bundles/avatar-videos/types/types.ts +++ b/shared/src/bundles/avatar-videos/types/types.ts @@ -1,6 +1,4 @@ export { type AvatarConfig } from './avatar-config.type.js'; -export { type GetAvatarVideoRequestDto } from './get-avatar-video-request-dto.type.js'; -export { type GetAvatarVideoResponseDto } from './get-avatar-video-response-dto.type.js'; export { type InputKind } from './input-kind.type.js'; export { type RenderAvatarVideoRequestDto } from './render-avatar-request-dto.type.js'; export { type RenderAvatarResponseDto } from './render-avatar-response-dto.type.js'; diff --git a/shared/src/index.ts b/shared/src/index.ts index ef4024c30..8e4e450fd 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -1,8 +1,6 @@ export { AuthApiPath } from './bundles/auth/auth.js'; export { type AvatarConfig, - type GetAvatarVideoRequestDto, - type GetAvatarVideoResponseDto, type InputKind, type RenderAvatarResponseDto, type RenderAvatarVideoRequestDto, From 008b8eae83951a5b7f05faa8f01a1737110bdc62 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Wed, 11 Sep 2024 13:14:30 +0300 Subject: [PATCH 22/22] OV-173: + const --- backend/src/bundles/avatar-videos/avatar-videos.service.ts | 7 ++----- backend/src/bundles/avatar-videos/constants/constnats.ts | 1 + .../avatar-videos/constants/request-delay.constant.ts | 3 +++ 3 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 backend/src/bundles/avatar-videos/constants/constnats.ts create mode 100644 backend/src/bundles/avatar-videos/constants/request-delay.constant.ts diff --git a/backend/src/bundles/avatar-videos/avatar-videos.service.ts b/backend/src/bundles/avatar-videos/avatar-videos.service.ts index 2fc978cac..8c7f05260 100644 --- a/backend/src/bundles/avatar-videos/avatar-videos.service.ts +++ b/backend/src/bundles/avatar-videos/avatar-videos.service.ts @@ -5,6 +5,7 @@ import { type AzureAIService } from '~/common/services/azure-ai/azure-ai.service import { type FileService } from '~/common/services/file/file.service.js'; import { type VideoService } from '../videos/video.service.js'; +import { REQUEST_DELAY } from './constants/constnats.js'; import { GenerateAvatarResponseStatus, RenderVideoErrorMessage, @@ -45,10 +46,6 @@ class AvatarVideoService { return this.fileService.getCloudFrontFileUrl(fileName); } - public removeAvatarVideo(id: string): Promise { - return this.azureAIService.removeAvatarVideo(id); - } - public async renderAvatarVideo( payload: RenderAvatarVideoRequestDto & { userId: string }, ): Promise { @@ -103,7 +100,7 @@ class AvatarVideoService { status: error.status, }); }); - }, 4000); + }, REQUEST_DELAY); } private async handleSuccessfulAvatarGeneration({ diff --git a/backend/src/bundles/avatar-videos/constants/constnats.ts b/backend/src/bundles/avatar-videos/constants/constnats.ts new file mode 100644 index 000000000..cad44c263 --- /dev/null +++ b/backend/src/bundles/avatar-videos/constants/constnats.ts @@ -0,0 +1 @@ +export { REQUEST_DELAY } from './request-delay.constant.js'; diff --git a/backend/src/bundles/avatar-videos/constants/request-delay.constant.ts b/backend/src/bundles/avatar-videos/constants/request-delay.constant.ts new file mode 100644 index 000000000..ce2d20189 --- /dev/null +++ b/backend/src/bundles/avatar-videos/constants/request-delay.constant.ts @@ -0,0 +1,3 @@ +const REQUEST_DELAY = 4000; + +export { REQUEST_DELAY };