(frontend) allow starting both a recording and a transcription

Major user feature request: allow starting recording and transcription
simultaneously. Inspired by Google Meet UX, add a subtle checkbox letting users
start a recording alongside transcription.

The backend support for this feature is not yet implemented and will come in
upcoming commits, I can only pass the options to the API. The update of the
notification service will be handled later.
We’re half way with a functional feature.

This is not enabled by default because screen recording is resource-intensive. I
prefer users opt in rather than making it their default choice until feature
usage and performance stabilize.
This commit is contained in:
lebaudantoine
2025-12-29 17:30:02 +01:00
committed by aleb_the_flash
parent 0d8c76cd03
commit 587a5bc574
4 changed files with 31 additions and 2 deletions

View File

@@ -181,6 +181,7 @@ class RecordingSerializer(serializers.ModelSerializer):
"updated_at",
"status",
"mode",
"options",
"key",
"is_expired",
"expired_at",
@@ -212,6 +213,11 @@ class StartRecordingSerializer(BaseValidationOnlySerializer):
"screen_recording or transcript.",
},
)
options = serializers.JSONField(
required=False,
allow_null=True,
default=dict,
)
class RequestEntrySerializer(BaseValidationOnlySerializer):

View File

@@ -308,10 +308,13 @@ class RoomViewSet(
)
mode = serializer.validated_data["mode"]
options = serializer.validated_data["options"]
room = self.get_object()
# May raise exception if an active or initiated recording already exist for the room
recording = models.Recording.objects.create(room=room, mode=mode)
recording = models.Recording.objects.create(
room=room, mode=mode, options=options
)
models.RecordingAccess.objects.create(
user=self.request.user, role=models.RoleChoices.OWNER, recording=recording

View File

@@ -7,16 +7,19 @@ import { RecordingMode } from '../types'
export interface StartRecordingParams {
id: string
mode?: RecordingMode
options?: Record<string, string | boolean>
}
const startRecording = ({
id,
mode = RecordingMode.Transcript,
options,
}: StartRecordingParams): Promise<ApiRoom> => {
return fetchApi(`rooms/${id}/start-recording/`, {
method: 'POST',
body: JSON.stringify({
mode: mode,
options: options,
}),
})
}

View File

@@ -40,6 +40,7 @@ export const TranscriptSidePanel = () => {
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState('')
const [includeScreenRecording, setIncludeScreenRecording] = useState(false)
const recordingSnap = useSnapshot(recordingStore)
@@ -99,6 +100,7 @@ export const TranscriptSidePanel = () => {
setIsLoading(true)
if (room.isRecording) {
await stopRecordingRoom({ id: roomId })
setIncludeScreenRecording(false)
recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING
await notifyParticipants({
type: NotificationType.TranscriptionStopped,
@@ -108,7 +110,20 @@ export const TranscriptSidePanel = () => {
room.localParticipant
)
} else {
await startRecordingRoom({ id: roomId, mode: RecordingMode.Transcript })
const recordingMode = includeScreenRecording
? RecordingMode.ScreenRecording
: RecordingMode.Transcript
const recordingOptions = {
language: 'fr', // fix hardcoded language
...(includeScreenRecording && { transcribe: true }),
}
await startRecordingRoom({
id: roomId,
mode: recordingMode,
options: recordingOptions,
})
recordingStore.status = RecordingStatus.TRANSCRIPT_STARTING
await notifyParticipants({
type: NotificationType.TranscriptionStarted,
@@ -454,6 +469,8 @@ export const TranscriptSidePanel = () => {
>
<Checkbox
size="sm"
isSelected={includeScreenRecording}
onChange={setIncludeScreenRecording}
isDisabled={
statuses.isStarting || statuses.isStarted || isPendingToStart
}