Skip to content

Commit

Permalink
Support experimental messages (#4)
Browse files Browse the repository at this point in the history
And demo debug messages in the example client
  • Loading branch information
mdepinet authored Sep 7, 2024
1 parent e0dfcc0 commit 2543741
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 10 deletions.
61 changes: 56 additions & 5 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class MyHomePage extends StatefulWidget {

class _MyHomePageState extends State<MyHomePage> {
UltravoxSession? _session;
bool debug = false;

@override
void dispose() {
Expand All @@ -60,7 +61,8 @@ class _MyHomePageState extends State<MyHomePage> {
return;
}
setState(() {
_session = UltravoxSession.create();
_session =
UltravoxSession.create(experimentalMessages: debug ? {"debug"} : {});
});
_session!.state.addListener(_onStateChange);
await _session!.joinCall(joinUrl);
Expand Down Expand Up @@ -94,10 +96,24 @@ class _MyHomePageState extends State<MyHomePage> {
mainAxisAlignment: MainAxisAlignment.center,
children: [
textInput,
ElevatedButton(
onPressed: () => _startCall(textController.text),
child: const Text('Start Call'),
),
const SizedBox(height: 20, width: 20),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
const Text.rich(TextSpan(
text: 'Debug',
style: TextStyle(fontWeight: FontWeight.bold))),
Switch(
value: debug,
onChanged: (value) => setState(() => debug = value),
),
const Spacer(),
ElevatedButton(
onPressed: () => _startCall(textController.text),
child: const Text('Start Call'),
),
],
)
],
),
));
Expand Down Expand Up @@ -128,6 +144,17 @@ class _MyHomePageState extends State<MyHomePage> {
child: const Text('End Call'),
),
);
if (debug) {
mainBodyChildren.add(const SizedBox(height: 20));
mainBodyChildren.add(const Text.rich(TextSpan(
text: 'Last Debug Message:',
style: TextStyle(fontWeight: FontWeight.w700))));

if (_session!.state.lastExperimentalMessage != null) {
mainBodyChildren.add(DebugMessageWidget(
message: _session!.state.lastExperimentalMessage!));
}
}
}
return Scaffold(
appBar: AppBar(
Expand Down Expand Up @@ -171,3 +198,27 @@ class TranscriptWidget extends StatelessWidget {
]));
}
}

class DebugMessageWidget extends StatelessWidget {
const DebugMessageWidget({super.key, required this.message});

final Map<String, dynamic> message;

@override
Widget build(BuildContext context) {
List<InlineSpan> children = [];
for (final entry in message.entries) {
children.add(TextSpan(
text: '${entry.key}: ',
style: const TextStyle(fontWeight: FontWeight.bold),
));
children.add(TextSpan(text: '${entry.value}\n'));
}
return RichText(
text: TextSpan(
style: Theme.of(context).textTheme.bodySmall,
children: children,
),
);
}
}
32 changes: 27 additions & 5 deletions lib/src/session.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ class Transcript {
class UltravoxSessionState extends ChangeNotifier {
final _transcripts = <Transcript>[];
var _status = UltravoxSessionStatus.disconnected;
Map<String, dynamic>? _lastExperimentalMessage;

UltravoxSessionStatus get status => _status;
List<Transcript> get transcripts => List.unmodifiable(_transcripts);
Map<String, dynamic>? get lastExperimentalMessage => _lastExperimentalMessage;

set status(UltravoxSessionStatus value) {
_status = value;
Expand All @@ -92,18 +94,26 @@ class UltravoxSessionState extends ChangeNotifier {
}
notifyListeners();
}

set lastExperimentalMessage(Map<String, dynamic>? value) {
_lastExperimentalMessage = value;
notifyListeners();
}
}

/// Manages a single session with Ultravox.
class UltravoxSession {
final _state = UltravoxSessionState();
final Set<String> _experimentalMessages;
final lk.Room _room;
final lk.EventsListener<lk.RoomEvent> _listener;
late WebSocketChannel _wsChannel;

UltravoxSession(this._room) : _listener = _room.createListener();
UltravoxSession(this._room, this._experimentalMessages)
: _listener = _room.createListener();

UltravoxSession.create() : this(lk.Room());
UltravoxSession.create({Set<String>? experimentalMessages})
: this(lk.Room(), experimentalMessages ?? {});

UltravoxSessionState get state => _state;

Expand All @@ -113,7 +123,15 @@ class UltravoxSession {
throw Exception('Cannot join a new call while already in a call');
}
_changeStatus(UltravoxSessionStatus.connecting);
_wsChannel = WebSocketChannel.connect(Uri.parse(joinUrl));
var url = Uri.parse(joinUrl);
if (_experimentalMessages.isNotEmpty) {
final queryParameters = Map<String, String>.from(url.queryParameters)
..addAll({
'experimentalMessages': _experimentalMessages.join(','),
});
url = url.replace(queryParameters: queryParameters);
}
_wsChannel = WebSocketChannel.connect(url);
await _wsChannel.ready;
_wsChannel.stream.listen((event) async {
await _handleSocketMessage(event);
Expand Down Expand Up @@ -195,7 +213,9 @@ class UltravoxSession {
}
break;
case 'transcript':
final medium = data['medium'] == 'voice' ? Medium.voice : Medium.text;
final medium = data['transcript']['medium'] == 'voice'
? Medium.voice
: Medium.text;
final transcript = Transcript(
text: data['transcript']['text'] as String,
isFinal: data['transcript']['final'] as bool,
Expand Down Expand Up @@ -231,7 +251,9 @@ class UltravoxSession {
}
break;
default:
// ignore
if (_experimentalMessages.isNotEmpty) {
_state.lastExperimentalMessage = data as Map<String, dynamic>;
}
}
}
}
7 changes: 7 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ topics:
- audio
- ai
- llms
platforms:
android:
ios:
linux:
macos:
web:
windows:

environment:
sdk: ^3.5.1
Expand Down

0 comments on commit 2543741

Please sign in to comment.