Skip to content

Commit a478e23

Browse files
authored
feat: add Transcription Event. (#531)
* feat: add Transcription Event. * dart format. * remove deprecated API. * print seg.text in example app.
1 parent 8c74825 commit a478e23

File tree

5 files changed

+98
-0
lines changed

5 files changed

+98
-0
lines changed

example/lib/widgets/participant.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,17 +84,26 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
8484
TrackPublication? get videoPublication;
8585
TrackPublication? get audioPublication;
8686
bool get isScreenShare => widget.type == ParticipantTrackType.kScreenShare;
87+
EventsListener<ParticipantEvent>? _listener;
8788

8889
@override
8990
void initState() {
9091
super.initState();
92+
_listener = widget.participant.createListener();
93+
_listener?.on<TranscriptionEvent>((e) {
94+
for (var seg in e.segments) {
95+
print('Transcription: ${seg.text} ${seg.isFinal}');
96+
}
97+
});
98+
9199
widget.participant.addListener(_onParticipantChanged);
92100
_onParticipantChanged();
93101
}
94102

95103
@override
96104
void dispose() {
97105
widget.participant.removeListener(_onParticipantChanged);
106+
_listener?.dispose();
98107
super.dispose();
99108
}
100109

lib/src/core/engine.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,18 @@ class Engine extends Disposable with EventsEmittable<EngineEvent> {
616616
packet: dp.user,
617617
kind: dp.kind,
618618
));
619+
} else if (dp.whichValue() == lk_models.DataPacket_Value.transcription) {
620+
// Transcription packet
621+
events.emit(EngineTranscriptionReceivedEvent(
622+
transcription: dp.transcription,
623+
));
624+
} else if (dp.whichValue() == lk_models.DataPacket_Value.sipDtmf) {
625+
// SIP DTMF packet
626+
events.emit(EngineSipDtmfReceivedEvent(
627+
dtmf: dp.sipDtmf,
628+
));
629+
} else {
630+
logger.warning('Unknown data packet type: ${dp.whichValue()}');
619631
}
620632
}
621633

lib/src/core/room.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
436436
..on<EngineActiveSpeakersUpdateEvent>(
437437
(event) => _onEngineActiveSpeakersUpdateEvent(event.speakers))
438438
..on<EngineDataPacketReceivedEvent>(_onDataMessageEvent)
439+
..on<EngineTranscriptionReceivedEvent>(_onTranscriptionEvent)
439440
..on<AudioPlaybackStarted>((event) {
440441
_handleAudioPlaybackStarted();
441442
})
@@ -683,6 +684,37 @@ class Room extends DisposableChangeNotifier with EventsEmittable<RoomEvent> {
683684
}
684685
}
685686

687+
void _onTranscriptionEvent(EngineTranscriptionReceivedEvent event) {
688+
final participant = getParticipantByIdentity(
689+
event.transcription.transcribedParticipantIdentity);
690+
if (participant == null) {
691+
return;
692+
}
693+
694+
final publication =
695+
participant.getTrackPublicationBySid(event.transcription.trackId);
696+
697+
var segments = event.transcription.segments.map((e) {
698+
return TranscriptionSegment(
699+
text: e.text,
700+
id: e.id,
701+
startTime: DateTime.fromMillisecondsSinceEpoch(e.startTime.toInt()),
702+
endTime: DateTime.fromMillisecondsSinceEpoch(e.endTime.toInt()),
703+
isFinal: e.final_5,
704+
language: e.language,
705+
);
706+
}).toList();
707+
708+
final transcription = TranscriptionEvent(
709+
participant: participant,
710+
publication: publication,
711+
segments: segments,
712+
);
713+
714+
participant.events.emit(transcription);
715+
events.emit(transcription);
716+
}
717+
686718
void _onDataMessageEvent(EngineDataPacketReceivedEvent dataPacketEvent) {
687719
// participant may be null if data is sent from Server-API
688720
final senderSid = dataPacketEvent.packet.participantSid;

lib/src/events.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,35 @@ class ParticipantPermissionsUpdatedEvent with RoomEvent, ParticipantEvent {
433433
'(participant: ${participant}, permissions: ${permissions})';
434434
}
435435

436+
class TranscriptionSegment {
437+
final String id;
438+
final String text;
439+
final DateTime startTime;
440+
final DateTime endTime;
441+
final bool isFinal;
442+
final String language;
443+
const TranscriptionSegment({
444+
required this.id,
445+
required this.text,
446+
required this.startTime,
447+
required this.endTime,
448+
required this.isFinal,
449+
required this.language,
450+
});
451+
}
452+
453+
/// Transcription event received from the server.
454+
class TranscriptionEvent with RoomEvent, ParticipantEvent {
455+
final Participant participant;
456+
final TrackPublication<Track>? publication;
457+
final List<TranscriptionSegment> segments;
458+
const TranscriptionEvent({
459+
required this.participant,
460+
required this.publication,
461+
required this.segments,
462+
});
463+
}
464+
436465
class ParticipantNameUpdatedEvent with RoomEvent, ParticipantEvent {
437466
final Participant participant;
438467
final String name;

lib/src/internal/events.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,22 @@ class EngineDataPacketReceivedEvent with EngineEvent, InternalEvent {
410410
});
411411
}
412412

413+
@internal
414+
class EngineTranscriptionReceivedEvent with EngineEvent, InternalEvent {
415+
final lk_models.Transcription transcription;
416+
const EngineTranscriptionReceivedEvent({
417+
required this.transcription,
418+
});
419+
}
420+
421+
@internal
422+
class EngineSipDtmfReceivedEvent with EngineEvent, InternalEvent {
423+
final lk_models.SipDTMF dtmf;
424+
const EngineSipDtmfReceivedEvent({
425+
required this.dtmf,
426+
});
427+
}
428+
413429
@internal
414430
abstract class DataChannelStateUpdatedEvent with EngineEvent, InternalEvent {
415431
final bool isPrimary;

0 commit comments

Comments
 (0)