From 8de4897042379830b1bdb0ae4ab9ee4ffe8a79cd Mon Sep 17 00:00:00 2001 From: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:21:57 +0530 Subject: [PATCH] feat: enable transcription automatically (#21691) * fest: Add enableAutomaticTranscription field to CalVideoSettings schema * fest: Update backend logic for enableAutomaticTranscription in event types * fest: Add frontend support for enableAutomaticTranscription in video meetings and event types * fest: Add localization strings for enableAutomaticTranscription feature * fix: enable transcription feature * Update apps/web/lib/video/[uid]/getServerSideProps.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --------- Co-authored-by: akarsh-jain-790 Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> --- .../web/lib/video/[uid]/getServerSideProps.ts | 20 +++++++++++++++++++ apps/web/modules/videos/ai/ai-transcribe.tsx | 20 ++++++++++++++++++- .../videos/views/videos-single-view.tsx | 7 +++++-- apps/web/public/static/locales/en/common.json | 1 + .../eventtypes/components/Locations.tsx | 16 +++++++++++++++ packages/features/eventtypes/lib/types.ts | 1 + packages/lib/server/repository/booking.ts | 1 + .../lib/server/repository/calVideoSettings.ts | 3 +++ packages/lib/server/repository/eventType.ts | 1 + .../event-types/hooks/useEventTypeForm.ts | 1 + .../migration.sql | 2 ++ packages/prisma/schema.prisma | 1 + .../server/routers/viewer/eventTypes/types.ts | 1 + .../viewer/eventTypes/update.handler.ts | 1 + 14 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 packages/prisma/migrations/20250528061149_add_transcription_setting/migration.sql diff --git a/apps/web/lib/video/[uid]/getServerSideProps.ts b/apps/web/lib/video/[uid]/getServerSideProps.ts index fdafeb6f99..7d5f5d4552 100644 --- a/apps/web/lib/video/[uid]/getServerSideProps.ts +++ b/apps/web/lib/video/[uid]/getServerSideProps.ts @@ -22,6 +22,7 @@ const md = new MarkdownIt("default", { html: true, breaks: true, linkify: true } type CalVideoSettings = { disableRecordingForGuests: boolean; disableRecordingForOrganizer: boolean; + enableAutomaticTranscription: boolean; }; const shouldEnableRecordButton = ({ @@ -43,6 +44,19 @@ const shouldEnableRecordButton = ({ return !calVideoSettings.disableRecordingForGuests; }; +const shouldEnableAutomaticTranscription = ({ + hasTeamPlan, + calVideoSettings, +}: { + hasTeamPlan: boolean; + calVideoSettings?: CalVideoSettings | null; +}) => { + if (!hasTeamPlan) return false; + if (!calVideoSettings) return false; + + return !!calVideoSettings.enableAutomaticTranscription; +}; + const checkIfUserIsHost = async ({ booking, sessionUserId, @@ -204,6 +218,11 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { isOrganizer: sessionUserId === bookingObj.user?.id, }); + const enableAutomaticTranscription = shouldEnableAutomaticTranscription({ + hasTeamPlan: !!hasTeamPlan, + calVideoSettings: bookingObj.eventType?.calVideoSettings, + }); + return { props: { meetingUrl: videoReference.meetingUrl ?? "", @@ -225,6 +244,7 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { displayLogInOverlay, loggedInUserName: sessionUserId ? session?.user?.name : undefined, showRecordingButton, + enableAutomaticTranscription, rediectAttendeeToOnExit: isOrganizer ? undefined : bookingObj.eventType?.calVideoSettings?.redirectUrlOnExit, diff --git a/apps/web/modules/videos/ai/ai-transcribe.tsx b/apps/web/modules/videos/ai/ai-transcribe.tsx index d8bdc65db9..c2576dc9d0 100644 --- a/apps/web/modules/videos/ai/ai-transcribe.tsx +++ b/apps/web/modules/videos/ai/ai-transcribe.tsx @@ -70,7 +70,13 @@ export interface DailyCustomTrayButton { tooltip: string; visualState?: DailyCustomTrayButtonVisualState; } -export const CalAiTranscribe = ({ showRecordingButton }: { showRecordingButton: boolean }) => { +export const CalAiTranscribe = ({ + showRecordingButton, + enableAutomaticTranscription, +}: { + showRecordingButton: boolean; + enableAutomaticTranscription: boolean; +}) => { const daily = useDaily(); const { t } = useLocale(); @@ -107,6 +113,18 @@ export const CalAiTranscribe = ({ showRecordingButton }: { showRecordingButton: }, []) ); + useDailyEvent("joined-meeting", (ev) => { + if (enableAutomaticTranscription) { + daily?.startTranscription(); + updateCustomTrayButtons({ + recording: BUTTONS.START_RECORDING, + transcription: transcription?.isTranscribing + ? BUTTONS.STOP_TRANSCRIPTION + : BUTTONS.START_TRANSCRIPTION, + }); + } + }); + useDailyEvent("transcription-started", (ev) => { updateCustomTrayButtons({ recording: recording?.isRecording ? BUTTONS.STOP_RECORDING : BUTTONS.START_RECORDING, diff --git a/apps/web/modules/videos/views/videos-single-view.tsx b/apps/web/modules/videos/views/videos-single-view.tsx index 54ae3d957d..bc3755f65b 100644 --- a/apps/web/modules/videos/views/videos-single-view.tsx +++ b/apps/web/modules/videos/views/videos-single-view.tsx @@ -36,6 +36,7 @@ export default function JoinCall(props: PageProps) { loggedInUserName, overrideName, showRecordingButton, + enableAutomaticTranscription, rediectAttendeeToOnExit, } = props; const [daily, setDaily] = useState(null); @@ -96,7 +97,6 @@ export default function JoinCall(props: PageProps) { callFrame = DailyIframe.getCallInstance(); } finally { setDaily(callFrame ?? null); - callFrame?.join(); } @@ -111,7 +111,10 @@ export default function JoinCall(props: PageProps) {
- +
{calVideoLogo ? ( diff --git a/apps/web/public/static/locales/en/common.json b/apps/web/public/static/locales/en/common.json index e407cc600f..c52d163382 100644 --- a/apps/web/public/static/locales/en/common.json +++ b/apps/web/public/static/locales/en/common.json @@ -47,6 +47,7 @@ "customize_calvideo_settings": "Customize Cal Video Settings", "calvideo_settings_description": "Configure video meeting preferences including recording permissions for hosts and attendees.", "disable_recording_for_guests": "Disable recording for guests", + "enable_automatic_transcription": "Enable automatic transcription after joining the meeting", "disable_recording_for_organizer": "Disable recording for organizer", "event_request_declined_recurring": "Your recurring event request has been declined", "event_request_cancelled": "Your scheduled event was canceled", diff --git a/packages/features/eventtypes/components/Locations.tsx b/packages/features/eventtypes/components/Locations.tsx index 503fc51f4f..1d59d41f3e 100644 --- a/packages/features/eventtypes/components/Locations.tsx +++ b/packages/features/eventtypes/components/Locations.tsx @@ -375,6 +375,22 @@ const Locations: React.FC = ({ }} /> )} + {!isPlatform && ( + { + return ( + + ); + }} + /> + )} { select: { disableRecordingForOrganizer: true, disableRecordingForGuests: true, + enableAutomaticTranscription: true, redirectUrlOnExit: true, }, },