orbit_voice 0.4.0 copy "orbit_voice: ^0.4.0" to clipboard
orbit_voice: ^0.4.0 copied to clipboard

Orbit Voice Flutter SDK — LiveKit connect, party-room audio (media stream, mic release, headset routing, VAD gate), no ovk_ in the client.

Orbit Voice (Flutter) #

Advanced Orbit Voice client for Flutter. Connect with a session from your Edge — never put ovk_ API keys in the app.

Noise cancellation #

On by default. Connect a room and the capture path runs DeepFilterNet 3 inside the WebRTC APM, after echo cancellation and noise suppression — so it removes the fans, traffic, keyboard and room hiss those stages leave behind, then an expander and soft limiter clean up the tail. No setup, no asset copying, no native toolchain in your app.

// Nothing required. This already denoises:
await engine.loginRoom(session);

Profiles #

engine.audio = OrbitAudioSettings.of(OrbitAudioProfile.balanced);
Profile Denoise Opus Use for
studio (default) full 64 kbps, DTX off hosts, podcasts, anything recorded
balanced full 48 kbps, DTX on large rooms, mobile data
lowData WebRTC only 24 kbps weak networks, low-end devices

Every field is individually settable when a preset is not quite right:

engine.audio = OrbitAudioSettings.of(OrbitAudioProfile.studio)
    .copyWith(denoiseStrength: 0.6, maxBitrate: 56000);

Talk vs. music rooms #

A speech-enhancement model treats a backing track as noise, so karaoke and listening rooms must not run it:

await engine.setRoomAudioMode(OrbitRoomAudioMode.music); // expander only
await engine.setRoomAudioMode(OrbitRoomAudioMode.talk);  // full chain

OrbitRoomAudioMode.music is for singing into the mic. Publishing a song file as its own LiveKit track is a separate, opt-in API (below).

Publish a song (opt-in) #

Backward compatible: if the app never calls publishSong, mic take / mute / seats / denoise behave exactly as before. Song publish is a second audio track (name: music); it is never mixed into the mic capture pipeline as the mic path.

await engine.publishSong(Uri.parse('https://example.com/clip.mp3'));
// or Uri.file('/path/to/song.m4a')

print(engine.isSongPublishing); // true while live
await engine.stopSong();

Listeners hear it as a normal remote LiveKit audio track. Do not also play the same file locally on listeners (double audio). Presence billing uses the same audio 1× rate as mic — one session per user even if mic + song are both open.

While the song is live the SDK switches to OrbitRoomAudioMode.music (and restores the previous mode on stopSong if it was the one that flipped it).

Turning it off #

await engine.setNoiseCancellation(false); // live A/B, or a user-facing switch

Checking it on device #

print(await engine.denoise?.stats());
// blocks > 0 means the stage is in the path; speechModelActive means the
// model itself is running, not just the expander.

What ships #

The model (7.6 MB) and the native library are bundled — Android arm64-v8a (11 MB) and iOS device plus arm64 simulator (31 MB). On other Android ABIs, on Intel simulators, and on web, the model is skipped and the expander runs alone. That path is a clean fallback, not an error.

Features (Rave-parity audio) #

  • DeepFilterNet 3 capture denoise with talk/music modes and a runtime toggle
  • Android media-stream ADM (USAGE_MEDIA / speech), HW APM off via flutter_webrtc 1.6+ options (no pub-cache patches)
  • 48 kHz sample rate for software NS
  • iOS playAndRecord + videoChat (not earpiece voiceChat)
  • Mic release after mute so other apps can record + audio focus release
  • Headset routing that does not jump to speaker during re-enumeration
  • Remote volume + VAD noise gate + stuck-silence heal
  • Speaking levels feed, op serialization, publish-permission wait
  • Pre-connect prefetch (TTL / claim)
  • OrbitSessionFetcher — host app supplies tokens
  • Opt-in publishSong / stopSong (second LiveKit audio track + billing)

Install #

dependencies:
  orbit_voice: ^0.4.0

Usage #

import 'package:orbit_voice/orbit_voice.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await OrbitAudioBootstrap.ensureInitialized();

  final engine = OrbitEngine.instance;
engine.sessionFetcher = ({
  required String roomId,
  required bool openMic,
  bool onSeat = false,
  bool leaveSeat = false,
  bool billingOnly = false,
}) async {
  // Call YOUR Edge — never ovk_ here.
  // leaveSeat/billingOnly → Edge /leave billing path.
  return OrbitVoiceSession.fromJson(await mintFromEdge(...));
};

  engine.prefetchSession(roomId); // on room tap
  // ...
  final session = await engine.fetchSessionCached(
    roomId: roomId,
    openMic: false,
  );
  if (session != null) await engine.loginRoom(session);
}

License #

Apache-2.0. LiveKit / WebRTC are Apache-2.0; DeepFilterNet and its model are MIT (assets/models/DeepFilterNet-LICENSE-MIT). Keep all three notices in your app’s open-source licenses screen.

0
likes
150
points
346
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Orbit Voice Flutter SDK — LiveKit connect, party-room audio (media stream, mic release, headset routing, VAD gate), no ovk_ in the client.

Homepage
Repository (GitHub)

License

MIT (license)

Dependencies

flutter, flutter_webrtc, livekit_client

More

Packages that depend on orbit_voice

Packages that implement orbit_voice