diff --git a/android/build.gradle b/android/build.gradle index 83ea883..907544b 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -128,7 +128,7 @@ dependencies { api 'com.facebook.react:react-native:+' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" api 'com.github.davidliu:audioswitch:89582c47c9a04c62f90aa5e57251af4800a62c9a' - api 'io.github.webrtc-sdk:android-prefixed:144.7559.15' + api 'io.github.webrtc-sdk:android-prefixed:150.7871.01' implementation "io.livekit:noise:2.0.0" implementation project(':livekit_react-native-webrtc') implementation "androidx.annotation:annotation:1.9.1" diff --git a/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt b/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt index a54aa27..ab5bf55 100644 --- a/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt +++ b/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt @@ -16,6 +16,12 @@ import java.util.concurrent.Callable object LiveKitReactNative { + // WARP: fold the DTLS handshake into the ICE handshake. Field trials are read + // when the PeerConnectionFactory is created, so this can only be set here, not + // from JS. The format is "Key/Value/" repeated, so this concatenates onto + // whatever the app already set. + private const val WARP_FIELD_TRIALS = "WebRTC-IceHandshakeDtls/Enabled/" + private var audioType: AudioType = AudioType.CommunicationAudioType() @@ -62,6 +68,7 @@ object LiveKitReactNative { this.audioType = audioType val options = WebRTCModuleOptions.getInstance() + options.fieldTrials = (options.fieldTrials ?: "") + WARP_FIELD_TRIALS options.videoEncoderFactory = CustomVideoEncoderFactory(null, true, true) options.videoDecoderFactory = CustomVideoDecoderFactory() options.enableMediaProjectionService = true diff --git a/ci/ios/Podfile b/ci/ios/Podfile index 3e2df09..8ba375f 100644 --- a/ci/ios/Podfile +++ b/ci/ios/Podfile @@ -5,6 +5,11 @@ require Pod::Executable.execute_command('node', ['-p', {paths: [process.argv[1]]}, )', __dir__]).strip +# LiveKitWebRTC 150.x is not on CocoaPods trunk yet; it only lives in livekit/podspecs. +# Remove both sources once the pod is published to trunk. +source 'https://github.com/livekit/podspecs.git' +source 'https://cdn.cocoapods.org/' + platform :ios, min_ios_version_supported prepare_react_native_project! diff --git a/ci/ios/Podfile.lock b/ci/ios/Podfile.lock index 50ee9a2..649c9d4 100644 --- a/ci/ios/Podfile.lock +++ b/ci/ios/Podfile.lock @@ -8,7 +8,7 @@ PODS: - hermes-engine (0.82.1): - hermes-engine/Pre-built (= 0.82.1) - hermes-engine/Pre-built (0.82.1) - - livekit-react-native (2.12.0): + - livekit-react-native (3.0.0): - boost - DoubleConversion - fast_float @@ -38,9 +38,9 @@ PODS: - SocketRocket - Yoga - livekit-react-native-webrtc (144.2.0): - - LiveKitWebRTC (= 144.7559.15) + - LiveKitWebRTC (= 150.7871.02) - React-Core - - LiveKitWebRTC (144.7559.15) + - LiveKitWebRTC (150.7871.02) - RCT-Folly (2024.11.18.00): - boost - DoubleConversion @@ -2525,8 +2525,9 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - trunk: + https://github.com/livekit/podspecs.git: - LiveKitWebRTC + trunk: - SocketRocket EXTERNAL SOURCES: @@ -2692,9 +2693,9 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 273e30e7fb618279934b0b95ffab60ecedb7acf5 - livekit-react-native: 27001a5d9454cc8d27894317425aa511801154e2 - livekit-react-native-webrtc: 3cd501a18d7ee8b95c21764dd8502201a0bc4cb3 - LiveKitWebRTC: 6abc86e190722e223fc870284547b6f229288c46 + livekit-react-native: 7a050816c891b58f073d4f7bda57ed7fe536a168 + livekit-react-native-webrtc: 5a5d397653822fcec6199c31dd48faa863b0b614 + LiveKitWebRTC: 31c0be28600e09057cb8414e12dec36c530773cb RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: f17e2ebc07876ca9ab8eb6e4b0a4e4647497ae3a RCTRequired: e2c574c1b45231f7efb0834936bd609d75072b63 @@ -2764,6 +2765,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb -PODFILE CHECKSUM: a7f2ec66657cfb895ebb19b63b9033e6419495f9 +PODFILE CHECKSUM: 1d02e1cbe60371e8cf7a5a04974ec742772db18d COCOAPODS: 1.16.2 diff --git a/ci/package.json b/ci/package.json index 7469483..dc8be2e 100644 --- a/ci/package.json +++ b/ci/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@livekit/react-native": "*", - "@livekit/react-native-webrtc": "^144.2.0", + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150", "@react-native/new-app-screen": "0.82.1", "livekit-client": "^2.19.0", "react": "19.1.1", diff --git a/ci/yarn.lock b/ci/yarn.lock index 6815603..194eadb 100644 --- a/ci/yarn.lock +++ b/ci/yarn.lock @@ -1952,15 +1952,15 @@ __metadata: languageName: node linkType: hard -"@livekit/react-native-webrtc@npm:^144.2.0": +"@livekit/react-native-webrtc@https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150": version: 144.2.0 - resolution: "@livekit/react-native-webrtc@npm:144.2.0" + resolution: "@livekit/react-native-webrtc@https://github.com/livekit/react-native-webrtc.git#commit=fc3525a8c5f775dbaf6367922d0a857f4896efa3" dependencies: base64-js: "npm:1.5.1" debug: "npm:4.3.4" peerDependencies: react-native: ">=0.60.0" - checksum: 10/fb2db76db47d976cd1ebfff16eef7ba49123a6b0c7af76c6cde671889276c7a5c8c6ed43d4402cf7412ff9905dbf4d986eaf029dd0190cd1bb6fb1897075dd72 + checksum: 10/8d5e0316e24e7c6af4d086806fb30db56dd54eb064728b07fa78defd2dd2004c43873206488f8b8cc8cfa2d70cabeace2e6efc498b7c18b15d5fcb084d6da8c1 languageName: node linkType: hard @@ -3550,7 +3550,7 @@ __metadata: "@babel/preset-env": "npm:^7.25.3" "@babel/runtime": "npm:^7.25.0" "@livekit/react-native": "npm:*" - "@livekit/react-native-webrtc": "npm:^144.2.0" + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150" "@react-native-community/cli": "npm:20.0.0" "@react-native-community/cli-platform-android": "npm:20.0.0" "@react-native-community/cli-platform-ios": "npm:20.0.0" diff --git a/example/ios/Podfile b/example/ios/Podfile index 4d8a793..9ff28fd 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -5,6 +5,11 @@ require Pod::Executable.execute_command('node', ['-p', {paths: [process.argv[1]]}, )', __dir__]).strip +# LiveKitWebRTC 150.x is not on CocoaPods trunk yet; it only lives in livekit/podspecs. +# Remove both sources once the pod is published to trunk. +source 'https://github.com/livekit/podspecs.git' +source 'https://cdn.cocoapods.org/' + platform :ios, min_ios_version_supported prepare_react_native_project! diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 0249e25..a42c0b6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -8,7 +8,7 @@ PODS: - hermes-engine (0.82.1): - hermes-engine/Pre-built (= 0.82.1) - hermes-engine/Pre-built (0.82.1) - - livekit-react-native (2.12.0): + - livekit-react-native (3.0.0): - boost - DoubleConversion - fast_float @@ -38,9 +38,9 @@ PODS: - SocketRocket - Yoga - livekit-react-native-webrtc (144.2.0): - - LiveKitWebRTC (= 144.7559.15) + - LiveKitWebRTC (= 150.7871.02) - React-Core - - LiveKitWebRTC (144.7559.15) + - LiveKitWebRTC (150.7871.02) - RCT-Folly (2024.11.18.00): - boost - DoubleConversion @@ -2617,8 +2617,9 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - trunk: + https://github.com/livekit/podspecs.git: - LiveKitWebRTC + trunk: - SocketRocket EXTERNAL SOURCES: @@ -2790,10 +2791,10 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 273e30e7fb618279934b0b95ffab60ecedb7acf5 - livekit-react-native: 27001a5d9454cc8d27894317425aa511801154e2 - livekit-react-native-webrtc: 3cd501a18d7ee8b95c21764dd8502201a0bc4cb3 - LiveKitWebRTC: 6abc86e190722e223fc870284547b6f229288c46 - RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f + livekit-react-native: 7a050816c891b58f073d4f7bda57ed7fe536a168 + livekit-react-native-webrtc: 5a5d397653822fcec6199c31dd48faa863b0b614 + LiveKitWebRTC: 31c0be28600e09057cb8414e12dec36c530773cb + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: f17e2ebc07876ca9ab8eb6e4b0a4e4647497ae3a RCTRequired: e2c574c1b45231f7efb0834936bd609d75072b63 RCTTypeSafety: c693294e3993056955c3010eb1ebc574f1fcded6 @@ -2865,6 +2866,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb -PODFILE CHECKSUM: a921a659e37cd7dfb12da519493e10c9f38400a1 +PODFILE CHECKSUM: 062e4aeb9a5d9962b035d1651584402d75e253b0 COCOAPODS: 1.16.2 diff --git a/example/package.json b/example/package.json index 5f35ed7..4de779b 100644 --- a/example/package.json +++ b/example/package.json @@ -10,7 +10,7 @@ "postinstall": "patch-package" }, "dependencies": { - "@livekit/react-native-webrtc": "^144.2.0", + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150", "@react-native-async-storage/async-storage": "^1.17.10", "@react-navigation/native": "^7.1.18", "@react-navigation/native-stack": "^7.3.27", diff --git a/ios/LivekitReactNative.m b/ios/LivekitReactNative.m index ea7b21e..fc855a7 100644 --- a/ios/LivekitReactNative.m +++ b/ios/LivekitReactNative.m @@ -11,6 +11,15 @@ +(void)setup { WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance]; options.videoEncoderFactory = simulcastVideoEncoderFactory; options.audioProcessingModule = LKAudioProcessingManager.sharedInstance.audioProcessingModule; + + // WebRTCModule only applies its own default field trials when fieldTrials is + // nil, so carry the dual-sim fix over ourselves. + // https://bugs.chromium.org/p/webrtc/issues/detail?id=10966 + options.fieldTrials = @{ + kLKRTCFieldTrialUseNWPathMonitor : kLKRTCFieldTrialEnabledValue, + // WARP: fold the DTLS handshake into the ICE handshake. + kLKRTCFieldTrialIceHandshakeDtlsKey : kLKRTCFieldTrialEnabledValue, + }; } @end diff --git a/package.json b/package.json index 0576939..86c2559 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.35.0", "@livekit/changesets-changelog-github": "^0.0.4", - "@livekit/react-native-webrtc": "^144.2.0", + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150", "@react-native/babel-preset": "0.83.0", "@react-native/eslint-config": "0.83.0", "@types/fastestsmallesttextencoderdecoder": "^1.0.0", diff --git a/src/index.tsx b/src/index.tsx index 3d5ed53..00f627e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -7,6 +7,7 @@ import './polyfills/MediaRecorderShim'; import { registerGlobals as webrtcRegisterGlobals, + RTCPeerConnection, AudioDeviceModule, AudioEngineMuteMode, AudioEngineAvailability, @@ -63,6 +64,7 @@ export function registerGlobals(options?: RegisterGlobalsOptions) { }; webrtcRegisterGlobals(); + shimSctpSnap(); if (opts.autoConfigureAudioSession) { setupIOSAudioManagement(); } @@ -76,6 +78,25 @@ export function registerGlobals(options?: RegisterGlobalsOptions) { setupNativeEvents(); } +function shimSctpSnap() { + // The SCTP half of WARP. livekit-client owns the RTCConfiguration it hands to + // `new RTCPeerConnection`, so there's no way to reach it from here. Default the + // flag on in the global constructor instead; an explicit `enableSctpSnap` in + // the app's rtcConfig still wins. + class SctpSnapPeerConnection extends RTCPeerConnection { + constructor( + configuration?: ConstructorParameters[0] + ) { + super({ enableSctpSnap: true, ...configuration }); + } + } + + // Cast rather than `declare global`, which would ship in the .d.ts and clash + // with whatever DOM types the consuming app has. + (globalThis as unknown as { RTCPeerConnection: unknown }).RTCPeerConnection = + SctpSnapPeerConnection; +} + function livekitRegisterGlobals() { let lkGlobal: LiveKitReactNativeInfo = { platform: Platform.OS, diff --git a/yarn.lock b/yarn.lock index 1663f73..0e640a7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3612,15 +3612,15 @@ __metadata: languageName: node linkType: hard -"@livekit/react-native-webrtc@npm:^144.2.0": +"@livekit/react-native-webrtc@https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150": version: 144.2.0 - resolution: "@livekit/react-native-webrtc@npm:144.2.0" + resolution: "@livekit/react-native-webrtc@https://github.com/livekit/react-native-webrtc.git#commit=fc3525a8c5f775dbaf6367922d0a857f4896efa3" dependencies: base64-js: "npm:1.5.1" debug: "npm:4.3.4" peerDependencies: react-native: ">=0.60.0" - checksum: 10/fb2db76db47d976cd1ebfff16eef7ba49123a6b0c7af76c6cde671889276c7a5c8c6ed43d4402cf7412ff9905dbf4d986eaf029dd0190cd1bb6fb1897075dd72 + checksum: 10/8d5e0316e24e7c6af4d086806fb30db56dd54eb064728b07fa78defd2dd2004c43873206488f8b8cc8cfa2d70cabeace2e6efc498b7c18b15d5fcb084d6da8c1 languageName: node linkType: hard @@ -3635,7 +3635,7 @@ __metadata: "@livekit/changesets-changelog-github": "npm:^0.0.4" "@livekit/components-react": "npm:^2.9.17" "@livekit/mutex": "npm:^1.1.1" - "@livekit/react-native-webrtc": "npm:^144.2.0" + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150" "@react-native/babel-preset": "npm:0.83.0" "@react-native/eslint-config": "npm:0.83.0" "@types/fastestsmallesttextencoderdecoder": "npm:^1.0.0" @@ -9538,7 +9538,7 @@ __metadata: "@babel/core": "npm:^7.25.2" "@babel/preset-env": "npm:^7.25.3" "@babel/runtime": "npm:^7.25.0" - "@livekit/react-native-webrtc": "npm:^144.2.0" + "@livekit/react-native-webrtc": "https://github.com/livekit/react-native-webrtc.git#bump-libwebrtc-to-m150" "@react-native-async-storage/async-storage": "npm:^1.17.10" "@react-native-community/cli": "npm:20.0.0" "@react-native-community/cli-platform-android": "npm:20.0.0"