✨(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:
committed by
aleb_the_flash
parent
0d8c76cd03
commit
587a5bc574
@@ -181,6 +181,7 @@ class RecordingSerializer(serializers.ModelSerializer):
|
|||||||
"updated_at",
|
"updated_at",
|
||||||
"status",
|
"status",
|
||||||
"mode",
|
"mode",
|
||||||
|
"options",
|
||||||
"key",
|
"key",
|
||||||
"is_expired",
|
"is_expired",
|
||||||
"expired_at",
|
"expired_at",
|
||||||
@@ -212,6 +213,11 @@ class StartRecordingSerializer(BaseValidationOnlySerializer):
|
|||||||
"screen_recording or transcript.",
|
"screen_recording or transcript.",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
options = serializers.JSONField(
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
default=dict,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class RequestEntrySerializer(BaseValidationOnlySerializer):
|
class RequestEntrySerializer(BaseValidationOnlySerializer):
|
||||||
|
|||||||
@@ -308,10 +308,13 @@ class RoomViewSet(
|
|||||||
)
|
)
|
||||||
|
|
||||||
mode = serializer.validated_data["mode"]
|
mode = serializer.validated_data["mode"]
|
||||||
|
options = serializer.validated_data["options"]
|
||||||
room = self.get_object()
|
room = self.get_object()
|
||||||
|
|
||||||
# May raise exception if an active or initiated recording already exist for the room
|
# 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(
|
models.RecordingAccess.objects.create(
|
||||||
user=self.request.user, role=models.RoleChoices.OWNER, recording=recording
|
user=self.request.user, role=models.RoleChoices.OWNER, recording=recording
|
||||||
|
|||||||
@@ -7,16 +7,19 @@ import { RecordingMode } from '../types'
|
|||||||
export interface StartRecordingParams {
|
export interface StartRecordingParams {
|
||||||
id: string
|
id: string
|
||||||
mode?: RecordingMode
|
mode?: RecordingMode
|
||||||
|
options?: Record<string, string | boolean>
|
||||||
}
|
}
|
||||||
|
|
||||||
const startRecording = ({
|
const startRecording = ({
|
||||||
id,
|
id,
|
||||||
mode = RecordingMode.Transcript,
|
mode = RecordingMode.Transcript,
|
||||||
|
options,
|
||||||
}: StartRecordingParams): Promise<ApiRoom> => {
|
}: StartRecordingParams): Promise<ApiRoom> => {
|
||||||
return fetchApi(`rooms/${id}/start-recording/`, {
|
return fetchApi(`rooms/${id}/start-recording/`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
mode: mode,
|
mode: mode,
|
||||||
|
options: options,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const TranscriptSidePanel = () => {
|
|||||||
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
|
const { t } = useTranslation('rooms', { keyPrefix: 'transcript' })
|
||||||
|
|
||||||
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState('')
|
const [isErrorDialogOpen, setIsErrorDialogOpen] = useState('')
|
||||||
|
const [includeScreenRecording, setIncludeScreenRecording] = useState(false)
|
||||||
|
|
||||||
const recordingSnap = useSnapshot(recordingStore)
|
const recordingSnap = useSnapshot(recordingStore)
|
||||||
|
|
||||||
@@ -99,6 +100,7 @@ export const TranscriptSidePanel = () => {
|
|||||||
setIsLoading(true)
|
setIsLoading(true)
|
||||||
if (room.isRecording) {
|
if (room.isRecording) {
|
||||||
await stopRecordingRoom({ id: roomId })
|
await stopRecordingRoom({ id: roomId })
|
||||||
|
setIncludeScreenRecording(false)
|
||||||
recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING
|
recordingStore.status = RecordingStatus.TRANSCRIPT_STOPPING
|
||||||
await notifyParticipants({
|
await notifyParticipants({
|
||||||
type: NotificationType.TranscriptionStopped,
|
type: NotificationType.TranscriptionStopped,
|
||||||
@@ -108,7 +110,20 @@ export const TranscriptSidePanel = () => {
|
|||||||
room.localParticipant
|
room.localParticipant
|
||||||
)
|
)
|
||||||
} else {
|
} 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
|
recordingStore.status = RecordingStatus.TRANSCRIPT_STARTING
|
||||||
await notifyParticipants({
|
await notifyParticipants({
|
||||||
type: NotificationType.TranscriptionStarted,
|
type: NotificationType.TranscriptionStarted,
|
||||||
@@ -454,6 +469,8 @@ export const TranscriptSidePanel = () => {
|
|||||||
>
|
>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
size="sm"
|
size="sm"
|
||||||
|
isSelected={includeScreenRecording}
|
||||||
|
onChange={setIncludeScreenRecording}
|
||||||
isDisabled={
|
isDisabled={
|
||||||
statuses.isStarting || statuses.isStarted || isPendingToStart
|
statuses.isStarting || statuses.isStarted || isPendingToStart
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user