Add livekit

This commit is contained in:
LittleSheep 2024-11-24 10:54:55 +08:00
parent ed32a31819
commit 66f41179ba
13 changed files with 62 additions and 135 deletions

View File

@ -12,7 +12,7 @@ plugins {
android { android {
namespace = "dev.solsynth.solian" namespace = "dev.solsynth.solian"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = "27.0.12077973"
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_17

View File

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip

View File

@ -18,7 +18,7 @@ pluginManagement {
plugins { plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "8.1.0" apply false id "com.android.application" version '8.7.2' apply false
// START: FlutterFire Configuration // START: FlutterFire Configuration
id "com.google.gms.google-services" version "4.3.15" apply false id "com.google.gms.google-services" version "4.3.15" apply false
id "com.google.firebase.crashlytics" version "2.8.1" apply false id "com.google.firebase.crashlytics" version "2.8.1" apply false

View File

@ -1,12 +0,0 @@
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:native_dio_adapter/native_dio_adapter.dart';
Dio addClientAdapter(Dio client) {
if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) {
// Switch to native implementation if possible
client.httpClientAdapter = NativeAdapter();
}
return client;
}

View File

@ -1,2 +0,0 @@
export 'package:surface/providers/adapters/sn_network_web.dart'
if (dart.library.io) 'package:surface/providers/adapters/sn_network_native.dart';

View File

@ -1,5 +0,0 @@
import 'package:dio/dio.dart';
Dio addClientAdapter(Dio client) {
return client;
}

View File

@ -5,7 +5,6 @@ import 'dart:developer';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:dio_smart_retry/dio_smart_retry.dart'; import 'package:dio_smart_retry/dio_smart_retry.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:surface/providers/adapters/sn_network_universal.dart';
import 'package:synchronized/synchronized.dart'; import 'package:synchronized/synchronized.dart';
const kAtkStoreKey = 'nex_user_atk'; const kAtkStoreKey = 'nex_user_atk';
@ -21,7 +20,7 @@ const kNetworkServerDirectory = [
]; ];
class SnNetworkProvider { class SnNetworkProvider {
late Dio client; late final Dio client;
late final SharedPreferences _prefs; late final SharedPreferences _prefs;
@ -53,8 +52,6 @@ class SnNetworkProvider {
), ),
); );
client = addClientAdapter(client);
SharedPreferences.getInstance().then((prefs) { SharedPreferences.getInstance().then((prefs) {
_prefs = prefs; _prefs = prefs;
client.options.baseUrl = client.options.baseUrl =

View File

@ -14,114 +14,7 @@ class CallRoomScreen extends StatefulWidget {
State<CallRoomScreen> createState() => _CallRoomScreenState(); State<CallRoomScreen> createState() => _CallRoomScreenState();
} }
const _kLocalWebRtcBaseUrl = 'http://localhost:8001';
class _CallRoomScreenState extends State<CallRoomScreen> { class _CallRoomScreenState extends State<CallRoomScreen> {
RTCPeerConnection? _peerConnection;
MediaStream? _localStream;
WebSocketChannel? _wsChannel;
@override
void initState() {
super.initState();
_initWebRtc();
}
Future<void> _initWebRtc() async {
final client = Dio();
client.options.baseUrl = _kLocalWebRtcBaseUrl;
final configResp = await client.get('/.well-known/webrtc');
// Get user media (audio only)
_localStream = await navigator.mediaDevices.getUserMedia({
'audio': true,
'video': false,
});
// Configure Peer Connection
Map<String, dynamic> config = {
'iceServers': configResp.data['ice_servers']
};
_peerConnection = await createPeerConnection(config);
// Add local stream to peer connection
_peerConnection?.addStream(_localStream!);
// Listen for ICE candidates
_peerConnection?.onIceCandidate = (RTCIceCandidate candidate) {
print('New ICE candidate: ${candidate.candidate}');
// Send the candidate to the signaling server
};
// Handle remote stream
_peerConnection?.onAddStream = (MediaStream stream) {
print('Remote stream added');
// Play the remote stream
};
_wsChannel = WebSocketChannel.connect(
Uri.parse('$_kLocalWebRtcBaseUrl/webrtc'),
);
await _wsChannel!.ready;
_wsChannel!.stream.listen((event) {
final Map<String, dynamic> data = jsonDecode(event);
switch (data['type']) {
case 'offer':
_handleOffer(data);
break;
case 'answer':
_handleAnswer(data);
break;
case 'candidate':
_handleCandidate(data);
break;
}
});
}
Future<void> _handleOffer(Map<String, dynamic> data) async {
// Set remote description
final offer = RTCSessionDescription(data['sdp'], data['type']);
await _peerConnection?.setRemoteDescription(offer);
// Create and send answer
final answer = await _peerConnection?.createAnswer();
await _peerConnection?.setLocalDescription(answer!);
_wsChannel?.sink.add({
'type': 'answer',
'sdp': answer?.sdp,
});
}
Future<void> _handleAnswer(Map<String, dynamic> data) async {
// Set remote description
final answer = RTCSessionDescription(data['sdp'], data['type']);
await _peerConnection?.setRemoteDescription(answer);
}
Future<void> _handleCandidate(Map<String, dynamic> data) async {
// Add ICE candidate
final candidate = RTCIceCandidate(
data['candidate'],
data['sdpMid'],
data['sdpMLineIndex'],
);
await _peerConnection?.addCandidate(candidate);
}
@override
void dispose() {
_wsChannel?.sink.close();
_localStream?.dispose();
_peerConnection?.close();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(

View File

@ -6,12 +6,14 @@ import FlutterMacOS
import Foundation import Foundation
import connectivity_plus import connectivity_plus
import device_info_plus
import file_selector_macos import file_selector_macos
import firebase_analytics import firebase_analytics
import firebase_core import firebase_core
import firebase_messaging import firebase_messaging
import flutter_udid import flutter_udid
import flutter_webrtc import flutter_webrtc
import livekit_client
import media_kit_libs_macos_video import media_kit_libs_macos_video
import media_kit_video import media_kit_video
import package_info_plus import package_info_plus
@ -26,12 +28,14 @@ import wakelock_plus
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin"))
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))

View File

@ -326,6 +326,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.10" version: "0.7.10"
device_info_plus:
dependency: transitive
description:
name: device_info_plus
sha256: f545ffbadee826f26f2e1a0f0cbd667ae9a6011cc0f77c0f8f00a969655e6e95
url: "https://pub.dev"
source: hosted
version: "11.1.1"
device_info_plus_platform_interface:
dependency: transitive
description:
name: device_info_plus_platform_interface
sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba"
url: "https://pub.dev"
source: hosted
version: "7.0.1"
dio: dio:
dependency: "direct main" dependency: "direct main"
description: description:
@ -643,7 +659,7 @@ packages:
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_webrtc: flutter_webrtc:
dependency: "direct main" dependency: transitive
description: description:
name: flutter_webrtc name: flutter_webrtc
sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f" sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f"
@ -946,6 +962,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.0" version: "5.0.0"
livekit_client:
dependency: "direct main"
description:
name: livekit_client
sha256: ad55045435fbf1a106e2da4c9a8d523755ce834db47f6d967beaa58228b21a05
url: "https://pub.dev"
source: hosted
version: "2.3.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -1250,6 +1274,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.1" version: "1.5.1"
protobuf:
dependency: transitive
description:
name: protobuf
sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
provider: provider:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1354,6 +1386,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.3" version: "0.1.3"
sdp_transform:
dependency: transitive
description:
name: sdp_transform
sha256: "73e412a5279a5c2de74001535208e20fff88f225c9a4571af0f7146202755e45"
url: "https://pub.dev"
source: hosted
version: "0.3.2"
sentry: sentry:
dependency: transitive dependency: transitive
description: description:
@ -1815,6 +1855,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.8.0" version: "5.8.0"
win32_registry:
dependency: transitive
description:
name: win32_registry
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
url: "https://pub.dev"
source: hosted
version: "1.1.5"
xdg_directories: xdg_directories:
dependency: transitive dependency: transitive
description: description:

View File

@ -88,7 +88,7 @@ dependencies:
pasteboard: ^0.3.0 pasteboard: ^0.3.0
sentry_flutter: ^8.10.1 sentry_flutter: ^8.10.1
synchronized: ^3.3.0+3 synchronized: ^3.3.0+3
flutter_webrtc: ^0.12.1+hotfix.1 livekit_client: ^2.3.0
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -11,6 +11,7 @@
#include <firebase_core/firebase_core_plugin_c_api.h> #include <firebase_core/firebase_core_plugin_c_api.h>
#include <flutter_udid/flutter_udid_plugin_c_api.h> #include <flutter_udid/flutter_udid_plugin_c_api.h>
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h> #include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
#include <livekit_client/live_kit_plugin.h>
#include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h> #include <media_kit_libs_windows_video/media_kit_libs_windows_video_plugin_c_api.h>
#include <media_kit_video/media_kit_video_plugin_c_api.h> #include <media_kit_video/media_kit_video_plugin_c_api.h>
#include <pasteboard/pasteboard_plugin.h> #include <pasteboard/pasteboard_plugin.h>
@ -29,6 +30,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("FlutterUdidPluginCApi")); registry->GetRegistrarForPlugin("FlutterUdidPluginCApi"));
FlutterWebRTCPluginRegisterWithRegistrar( FlutterWebRTCPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterWebRTCPlugin")); registry->GetRegistrarForPlugin("FlutterWebRTCPlugin"));
LiveKitPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("LiveKitPlugin"));
MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar( MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi")); registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi"));
MediaKitVideoPluginCApiRegisterWithRegistrar( MediaKitVideoPluginCApiRegisterWithRegistrar(

View File

@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
firebase_core firebase_core
flutter_udid flutter_udid
flutter_webrtc flutter_webrtc
livekit_client
media_kit_libs_windows_video media_kit_libs_windows_video
media_kit_video media_kit_video
pasteboard pasteboard