From a6fc49dcbcb43737858a3f60fc02dde94c60e37b Mon Sep 17 00:00:00 2001 From: davidliu Date: Wed, 9 Sep 2026 18:19:14 +0900 Subject: [PATCH 1/3] ios,android: move to prefixed webrtc --- .changeset/prefixed-webrtc-symbols.md | 14 ++++++++++++ README.md | 10 +++++++++ android/build.gradle | 2 +- .../livekit/reactnative/LiveKitReactNative.kt | 2 +- .../reactnative/LivekitReactNativeModule.kt | 2 +- .../AudioRecordSamplesDispatcher.kt | 4 ++-- .../audio/processing/AudioSinkManager.kt | 4 ++-- .../audio/processing/AudioSinkProcessor.kt | 2 +- .../CustomAudioProcessingFactory.kt | 2 +- .../processing/MultibandVolumeProcessor.kt | 2 +- .../audio/processing/VolumeProcessor.kt | 2 +- .../video/CustomVideoDecoderFactory.kt | 12 +++++----- .../video/CustomVideoEncoderFactory.kt | 10 ++++----- .../SimulcastVideoEncoderFactoryWrapper.kt | 22 +++++++++---------- .../video/WrappedVideoDecoderFactoryProxy.kt | 8 +++---- .../webrtc/audio/WebRtcAudioTrackHelper.kt | 2 +- ci/ios/Podfile | 3 +++ eslint.config.mjs | 2 +- .../project.pbxproj | 4 ++-- example/ios/Podfile | 3 +++ example/ios/Podfile.lock | 17 +++++++------- ios/Headers/LKAudioProcessingAdapter.h | 10 ++++----- ios/Headers/LKAudioProcessingManager.h | 12 +++++----- ios/LKAudioProcessingAdapter.m | 16 +++++++------- ios/LKAudioProcessingManager.m | 10 ++++----- ios/LiveKitReactNativeModule.swift | 20 ++++++++--------- ios/LivekitReactNative.m | 4 ++-- ios/audio/AudioProcessing.swift | 2 +- ios/audio/AudioRendererManager.swift | 14 ++++++------ ios/audio/AudioSinkRenderer.swift | 2 +- ios/audio/MultibandVolumeAudioRenderer.swift | 2 +- ios/audio/VolumeAudioRenderer.swift | 2 +- 32 files changed, 127 insertions(+), 96 deletions(-) create mode 100644 .changeset/prefixed-webrtc-symbols.md rename android/src/main/java/{ => livekit}/org/webrtc/audio/WebRtcAudioTrackHelper.kt (94%) diff --git a/.changeset/prefixed-webrtc-symbols.md b/.changeset/prefixed-webrtc-symbols.md new file mode 100644 index 00000000..4e077ed9 --- /dev/null +++ b/.changeset/prefixed-webrtc-symbols.md @@ -0,0 +1,14 @@ +--- +'@livekit/react-native': major +--- + +Move to the prefixed WebRTC builds: `io.github.webrtc-sdk:android-prefixed` on Android and the `LiveKitWebRTC` pod on iOS. + +iOS apps must add the LiveKit podspec source to their `Podfile`, since `LiveKitWebRTC` is not published on the CocoaPods trunk: + +```ruby +source 'https://cdn.cocoapods.org/' +source 'https://github.com/livekit/podspecs.git' +``` + +Apps that only use the JavaScript API need no other changes. Native integrations must migrate to the prefixed symbols: `org.webrtc.*` becomes `livekit.org.webrtc.*` on Android, and libwebrtc Objective-C types gain an `LK` prefix on iOS (`RTCAudioRenderer` becomes `LKRTCAudioRenderer`, `RTCAudioBuffer` becomes `LKRTCAudioBuffer`, and so on). Custom `-keep class org.webrtc.**` ProGuard rules must be updated to `livekit.org.webrtc.**`. diff --git a/README.md b/README.md index 38653824..bb72d852 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,16 @@ This library depends on `@livekit/react-native-webrtc`, which has additional ins - [iOS Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/iOSInstallation.md) - [Android Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/AndroidInstallation.md) +On iOS, the underlying `LiveKitWebRTC` pod is published from +[livekit/podspecs](https://github.com/livekit/podspecs) rather than the CocoaPods trunk, so add both +sources at the top of your `Podfile`. Both lines are required: declaring any source disables the +implicit trunk default, and the rest of your pods would no longer resolve. + +```ruby +source 'https://cdn.cocoapods.org/' +source 'https://github.com/livekit/podspecs.git' +``` + --- Once the `@livekit/react-native-webrtc` dependency is installed, one last step is needed to finish the installation: diff --git a/android/build.gradle b/android/build.gradle index 4d1faae3..83ea8830 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:144.7559.04' + api 'io.github.webrtc-sdk:android-prefixed:144.7559.15' 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 01b6e764..a54aa27e 100644 --- a/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt +++ b/android/src/main/java/com/livekit/reactnative/LiveKitReactNative.kt @@ -11,7 +11,7 @@ import com.livekit.reactnative.audio.processing.CustomAudioProcessingController import com.livekit.reactnative.video.CustomVideoDecoderFactory import com.livekit.reactnative.video.CustomVideoEncoderFactory import com.oney.WebRTCModule.WebRTCModuleOptions -import org.webrtc.audio.JavaAudioDeviceModule +import livekit.org.webrtc.audio.JavaAudioDeviceModule import java.util.concurrent.Callable object LiveKitReactNative { diff --git a/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt b/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt index f78e7289..ece4fcb5 100644 --- a/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt +++ b/android/src/main/java/com/livekit/reactnative/LivekitReactNativeModule.kt @@ -18,7 +18,7 @@ import com.livekit.reactnative.audio.processing.AudioSinkProcessor import com.livekit.reactnative.audio.processing.MultibandVolumeProcessor import com.livekit.reactnative.audio.processing.VolumeProcessor import com.oney.WebRTCModule.WebRTCModuleOptions -import org.webrtc.audio.WebRtcAudioTrackHelper +import livekit.org.webrtc.audio.WebRtcAudioTrackHelper import java.lang.Thread.sleep import kotlin.concurrent.thread import kotlin.time.Duration.Companion.milliseconds diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioRecordSamplesDispatcher.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioRecordSamplesDispatcher.kt index 13d8585b..85c80724 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioRecordSamplesDispatcher.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioRecordSamplesDispatcher.kt @@ -18,8 +18,8 @@ package com.livekit.reactnative.audio.processing import android.media.AudioFormat import android.os.SystemClock -import org.webrtc.AudioTrackSink -import org.webrtc.audio.JavaAudioDeviceModule +import livekit.org.webrtc.AudioTrackSink +import livekit.org.webrtc.audio.JavaAudioDeviceModule import java.nio.ByteBuffer import java.util.Collections diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkManager.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkManager.kt index 4ee41868..ab28b4e5 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkManager.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkManager.kt @@ -3,8 +3,8 @@ package com.livekit.reactnative.audio.processing import com.facebook.react.bridge.ReactContext import com.livekit.reactnative.LiveKitReactNative import com.oney.WebRTCModule.WebRTCModule -import org.webrtc.AudioTrack -import org.webrtc.AudioTrackSink +import livekit.org.webrtc.AudioTrack +import livekit.org.webrtc.AudioTrackSink import java.util.Collections import java.util.UUID diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkProcessor.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkProcessor.kt index ca8c671c..02e197c1 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkProcessor.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/AudioSinkProcessor.kt @@ -4,7 +4,7 @@ import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReactContext import com.facebook.react.modules.core.DeviceEventManagerModule import com.livekit.reactnative.audio.events.Events -import org.webrtc.AudioTrackSink +import livekit.org.webrtc.AudioTrackSink import java.nio.ByteBuffer import java.util.Arrays import kotlin.io.encoding.Base64 diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/CustomAudioProcessingFactory.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/CustomAudioProcessingFactory.kt index 17f506dd..44ee38e5 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/CustomAudioProcessingFactory.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/CustomAudioProcessingFactory.kt @@ -1,6 +1,6 @@ package com.livekit.reactnative.audio.processing -import org.webrtc.ExternalAudioProcessingFactory +import livekit.org.webrtc.ExternalAudioProcessingFactory import java.nio.ByteBuffer /** diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/MultibandVolumeProcessor.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/MultibandVolumeProcessor.kt index b41314e8..397599a2 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/MultibandVolumeProcessor.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/MultibandVolumeProcessor.kt @@ -14,7 +14,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.transform import kotlinx.coroutines.launch -import org.webrtc.AudioTrackSink +import livekit.org.webrtc.AudioTrackSink import java.nio.ByteBuffer import kotlin.math.pow import kotlin.math.round diff --git a/android/src/main/java/com/livekit/reactnative/audio/processing/VolumeProcessor.kt b/android/src/main/java/com/livekit/reactnative/audio/processing/VolumeProcessor.kt index 802eae86..df73fe68 100644 --- a/android/src/main/java/com/livekit/reactnative/audio/processing/VolumeProcessor.kt +++ b/android/src/main/java/com/livekit/reactnative/audio/processing/VolumeProcessor.kt @@ -4,7 +4,7 @@ import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.ReactContext import com.facebook.react.modules.core.DeviceEventManagerModule import com.livekit.reactnative.audio.events.Events -import org.webrtc.AudioTrackSink +import livekit.org.webrtc.AudioTrackSink import java.nio.ByteBuffer import kotlin.math.round import kotlin.math.sqrt diff --git a/android/src/main/java/com/livekit/reactnative/video/CustomVideoDecoderFactory.kt b/android/src/main/java/com/livekit/reactnative/video/CustomVideoDecoderFactory.kt index 9b318e08..ed193432 100644 --- a/android/src/main/java/com/livekit/reactnative/video/CustomVideoDecoderFactory.kt +++ b/android/src/main/java/com/livekit/reactnative/video/CustomVideoDecoderFactory.kt @@ -17,12 +17,12 @@ package com.livekit.reactnative.video import com.oney.WebRTCModule.webrtcutils.SoftwareVideoDecoderFactoryProxy -import org.webrtc.EglBase -import org.webrtc.SoftwareVideoDecoderFactory -import org.webrtc.VideoCodecInfo -import org.webrtc.VideoDecoder -import org.webrtc.VideoDecoderFactory -import org.webrtc.WrappedVideoDecoderFactory +import livekit.org.webrtc.EglBase +import livekit.org.webrtc.SoftwareVideoDecoderFactory +import livekit.org.webrtc.VideoCodecInfo +import livekit.org.webrtc.VideoDecoder +import livekit.org.webrtc.VideoDecoderFactory +import livekit.org.webrtc.WrappedVideoDecoderFactory open class CustomVideoDecoderFactory( private var forceSWCodec: Boolean = false, diff --git a/android/src/main/java/com/livekit/reactnative/video/CustomVideoEncoderFactory.kt b/android/src/main/java/com/livekit/reactnative/video/CustomVideoEncoderFactory.kt index 741798d6..1259f90a 100644 --- a/android/src/main/java/com/livekit/reactnative/video/CustomVideoEncoderFactory.kt +++ b/android/src/main/java/com/livekit/reactnative/video/CustomVideoEncoderFactory.kt @@ -17,11 +17,11 @@ package com.livekit.reactnative.video import com.oney.WebRTCModule.webrtcutils.SoftwareVideoEncoderFactoryProxy -import org.webrtc.EglBase -import org.webrtc.SoftwareVideoEncoderFactory -import org.webrtc.VideoCodecInfo -import org.webrtc.VideoEncoder -import org.webrtc.VideoEncoderFactory +import livekit.org.webrtc.EglBase +import livekit.org.webrtc.SoftwareVideoEncoderFactory +import livekit.org.webrtc.VideoCodecInfo +import livekit.org.webrtc.VideoEncoder +import livekit.org.webrtc.VideoEncoderFactory open class CustomVideoEncoderFactory( sharedContext: EglBase.Context?, diff --git a/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt b/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt index 0025ba30..d035ac5a 100644 --- a/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt +++ b/android/src/main/java/com/livekit/reactnative/video/SimulcastVideoEncoderFactoryWrapper.kt @@ -2,17 +2,17 @@ package com.livekit.reactnative.video import android.util.Log import com.oney.WebRTCModule.webrtcutils.SoftwareVideoEncoderFactoryProxy -import org.webrtc.EglBase -import org.webrtc.HardwareVideoEncoderFactory -import org.webrtc.SimulcastVideoEncoderFactory -import org.webrtc.SoftwareVideoEncoderFactory -import org.webrtc.VideoCodecInfo -import org.webrtc.VideoCodecStatus -import org.webrtc.VideoEncoder -import org.webrtc.VideoEncoderFactory -import org.webrtc.VideoEncoderFallback -import org.webrtc.VideoFrame -import org.webrtc.WrappedNativeVideoEncoder +import livekit.org.webrtc.EglBase +import livekit.org.webrtc.HardwareVideoEncoderFactory +import livekit.org.webrtc.SimulcastVideoEncoderFactory +import livekit.org.webrtc.SoftwareVideoEncoderFactory +import livekit.org.webrtc.VideoCodecInfo +import livekit.org.webrtc.VideoCodecStatus +import livekit.org.webrtc.VideoEncoder +import livekit.org.webrtc.VideoEncoderFactory +import livekit.org.webrtc.VideoEncoderFallback +import livekit.org.webrtc.VideoFrame +import livekit.org.webrtc.WrappedNativeVideoEncoder import java.util.concurrent.Callable import java.util.concurrent.ExecutorService import java.util.concurrent.Executors diff --git a/android/src/main/java/com/livekit/reactnative/video/WrappedVideoDecoderFactoryProxy.kt b/android/src/main/java/com/livekit/reactnative/video/WrappedVideoDecoderFactoryProxy.kt index 48386610..372d3b49 100644 --- a/android/src/main/java/com/livekit/reactnative/video/WrappedVideoDecoderFactoryProxy.kt +++ b/android/src/main/java/com/livekit/reactnative/video/WrappedVideoDecoderFactoryProxy.kt @@ -1,10 +1,10 @@ package com.livekit.reactnative.video import com.oney.WebRTCModule.EglUtils -import org.webrtc.VideoCodecInfo -import org.webrtc.VideoDecoder -import org.webrtc.VideoDecoderFactory -import org.webrtc.WrappedVideoDecoderFactory +import livekit.org.webrtc.VideoCodecInfo +import livekit.org.webrtc.VideoDecoder +import livekit.org.webrtc.VideoDecoderFactory +import livekit.org.webrtc.WrappedVideoDecoderFactory class WrappedVideoDecoderFactoryProxy : VideoDecoderFactory { diff --git a/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt b/android/src/main/java/livekit/org/webrtc/audio/WebRtcAudioTrackHelper.kt similarity index 94% rename from android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt rename to android/src/main/java/livekit/org/webrtc/audio/WebRtcAudioTrackHelper.kt index 7b256af2..af069167 100644 --- a/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt +++ b/android/src/main/java/livekit/org/webrtc/audio/WebRtcAudioTrackHelper.kt @@ -1,4 +1,4 @@ -package org.webrtc.audio +package livekit.org.webrtc.audio import android.media.AudioAttributes diff --git a/ci/ios/Podfile b/ci/ios/Podfile index 3e2df095..a026024c 100644 --- a/ci/ios/Podfile +++ b/ci/ios/Podfile @@ -1,3 +1,6 @@ +source 'https://cdn.cocoapods.org/' +source 'https://github.com/livekit/podspecs.git' + # Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( diff --git a/eslint.config.mjs b/eslint.config.mjs index 09f2d08a..9bd580de 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -33,6 +33,6 @@ export default defineConfig([ }, }, { - ignores: ['node_modules/', 'lib/', 'docs/', 'src/polyfills/'], + ignores: ['node_modules/', 'lib/', 'docs/', 'src/polyfills/', '**/.yalc/'], }, ]); diff --git a/example/ios/LivekitReactNativeExample.xcodeproj/project.pbxproj b/example/ios/LivekitReactNativeExample.xcodeproj/project.pbxproj index 44c2c70e..bc4a24cc 100644 --- a/example/ios/LivekitReactNativeExample.xcodeproj/project.pbxproj +++ b/example/ios/LivekitReactNativeExample.xcodeproj/project.pbxproj @@ -366,12 +366,12 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-LivekitReactNativeExample/Pods-LivekitReactNativeExample-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/WebRTC-SDK/WebRTC.framework/WebRTC", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/LiveKitWebRTC/LiveKitWebRTC.framework/LiveKitWebRTC", "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermesvm.framework/hermesvm", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/LiveKitWebRTC.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermesvm.framework", ); runOnlyForDeploymentPostprocessing = 0; diff --git a/example/ios/Podfile b/example/ios/Podfile index 4d8a7930..a3bb4ae0 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,3 +1,6 @@ +source 'https://cdn.cocoapods.org/' +source 'https://github.com/livekit/podspecs.git' + # Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 1e77af90..43ea8632 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.11.0): + - livekit-react-native (2.12.0): - boost - DoubleConversion - fast_float @@ -38,8 +38,9 @@ PODS: - SocketRocket - Yoga - livekit-react-native-webrtc (144.1.2): + - LiveKitWebRTC (= 144.7559.15) - React-Core - - WebRTC-SDK (= 144.7559.10) + - LiveKitWebRTC (144.7559.15) - RCT-Folly (2024.11.18.00): - boost - DoubleConversion @@ -2530,7 +2531,6 @@ PODS: - SocketRocket - Yoga - SocketRocket (0.7.1) - - WebRTC-SDK (144.7559.10) - Yoga (0.0.0) DEPENDENCIES: @@ -2617,9 +2617,10 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: + https://github.com/livekit/podspecs.git: + - LiveKitWebRTC trunk: - SocketRocket - - WebRTC-SDK EXTERNAL SOURCES: boost: @@ -2790,8 +2791,9 @@ SPEC CHECKSUMS: fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 hermes-engine: 273e30e7fb618279934b0b95ffab60ecedb7acf5 - livekit-react-native: b8a86fb1c57270437f8a010437c0570585a13625 - livekit-react-native-webrtc: 5ff3e8d229a3fcd34f99fe4cb1c2c93f92017b0c + livekit-react-native: 27001a5d9454cc8d27894317425aa511801154e2 + livekit-react-native-webrtc: 8ac4a8c004158ec95db235b6c6a818dee66df0a4 + LiveKitWebRTC: c055d3954f3c3f17f0e327f72b8e91a6c3ebcc47 RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f RCTDeprecation: f17e2ebc07876ca9ab8eb6e4b0a4e4647497ae3a RCTRequired: e2c574c1b45231f7efb0834936bd609d75072b63 @@ -2862,9 +2864,8 @@ SPEC CHECKSUMS: RNCAsyncStorage: 01e4301688a611936e3644746ffe3325d3181952 RNScreens: 0bbf16c074ae6bb1058a7bf2d1ae017f4306797c SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - WebRTC-SDK: 1d7fc2ae91da6edd63e25f3882ff24f86a8d9d8b Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb -PODFILE CHECKSUM: a921a659e37cd7dfb12da519493e10c9f38400a1 +PODFILE CHECKSUM: 841abb8b2992cf16bb758bde8cf7f8cdbfb22695 COCOAPODS: 1.16.2 diff --git a/ios/Headers/LKAudioProcessingAdapter.h b/ios/Headers/LKAudioProcessingAdapter.h index f7327080..12bbfb19 100644 --- a/ios/Headers/LKAudioProcessingAdapter.h +++ b/ios/Headers/LKAudioProcessingAdapter.h @@ -1,17 +1,17 @@ #import -#import +#import @protocol LKExternalAudioProcessingDelegate - (void)audioProcessingInitializeWithSampleRate:(size_t)sampleRateHz channels:(size_t)channels; -- (void)audioProcessingProcess:(RTC_OBJC_TYPE(RTCAudioBuffer) * _Nonnull)audioBuffer; +- (void)audioProcessingProcess:(LKRTCAudioBuffer * _Nonnull)audioBuffer; - (void)audioProcessingRelease; @end -@interface LKAudioProcessingAdapter : NSObject +@interface LKAudioProcessingAdapter : NSObject - (nonnull instancetype)init; @@ -19,8 +19,8 @@ - (void)removeProcessing:(id _Nonnull)processor; -- (void)addAudioRenderer:(nonnull id)renderer; +- (void)addAudioRenderer:(nonnull id)renderer; -- (void)removeAudioRenderer:(nonnull id)renderer; +- (void)removeAudioRenderer:(nonnull id)renderer; @end \ No newline at end of file diff --git a/ios/Headers/LKAudioProcessingManager.h b/ios/Headers/LKAudioProcessingManager.h index 332b85c5..e86a5c20 100644 --- a/ios/Headers/LKAudioProcessingManager.h +++ b/ios/Headers/LKAudioProcessingManager.h @@ -1,10 +1,10 @@ #import -#import +#import #import "LKAudioProcessingAdapter.h" @interface LKAudioProcessingManager : NSObject -@property(nonatomic, strong) RTCDefaultAudioProcessingModule* _Nonnull audioProcessingModule; +@property(nonatomic, strong) LKRTCDefaultAudioProcessingModule* _Nonnull audioProcessingModule; @property(nonatomic, strong) LKAudioProcessingAdapter* _Nonnull capturePostProcessingAdapter; @@ -13,13 +13,13 @@ + (_Nonnull instancetype)sharedInstance; -- (void)addLocalAudioRenderer:(nonnull id)renderer; +- (void)addLocalAudioRenderer:(nonnull id)renderer; -- (void)removeLocalAudioRenderer:(nonnull id)renderer; +- (void)removeLocalAudioRenderer:(nonnull id)renderer; -- (void)addRemoteAudioRenderer:(nonnull id)renderer; +- (void)addRemoteAudioRenderer:(nonnull id)renderer; -- (void)removeRemoteAudioRenderer:(nonnull id)renderer; +- (void)removeRemoteAudioRenderer:(nonnull id)renderer; - (void)addCapturePostProcessor:(nonnull id)processor; diff --git a/ios/LKAudioProcessingAdapter.m b/ios/LKAudioProcessingAdapter.m index 1d638246..e80b4238 100644 --- a/ios/LKAudioProcessingAdapter.m +++ b/ios/LKAudioProcessingAdapter.m @@ -1,9 +1,9 @@ #import "LKAudioProcessingAdapter.h" -#import +#import #import @implementation LKAudioProcessingAdapter { - NSMutableArray>* _renderers; + NSMutableArray>* _renderers; NSMutableArray>* _processors; os_unfair_lock _lock; BOOL _isAudioProcessingInitialized; @@ -16,7 +16,7 @@ - (instancetype)init { if (self) { _isAudioProcessingInitialized = NO; _lock = OS_UNFAIR_LOCK_INIT; - _renderers = [[NSMutableArray> alloc] init]; + _renderers = [[NSMutableArray> alloc] init]; _processors = [[NSMutableArray> alloc] init]; } return self; @@ -41,13 +41,13 @@ - (void)removeProcessing:(id _Nonnull)process os_unfair_lock_unlock(&_lock); } -- (void)addAudioRenderer:(nonnull id)renderer { +- (void)addAudioRenderer:(nonnull id)renderer { os_unfair_lock_lock(&_lock); [_renderers addObject:renderer]; os_unfair_lock_unlock(&_lock); } -- (void)removeAudioRenderer:(nonnull id)renderer { +- (void)removeAudioRenderer:(nonnull id)renderer { os_unfair_lock_lock(&_lock); _renderers = [[_renderers filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, @@ -69,7 +69,7 @@ - (void)audioProcessingInitializeWithSampleRate:(size_t)sampleRateHz channels:(s os_unfair_lock_unlock(&_lock); } -- (AVAudioPCMBuffer*)toPCMBuffer:(RTC_OBJC_TYPE(RTCAudioBuffer) *)audioBuffer { +- (AVAudioPCMBuffer*)toPCMBuffer:(LKRTCAudioBuffer *)audioBuffer { AVAudioFormat* format = [[AVAudioFormat alloc] initWithCommonFormat:AVAudioPCMFormatInt16 sampleRate:audioBuffer.frames * 100.0 @@ -93,13 +93,13 @@ - (AVAudioPCMBuffer*)toPCMBuffer:(RTC_OBJC_TYPE(RTCAudioBuffer) *)audioBuffer { return pcmBuffer; } -- (void)audioProcessingProcess:(RTC_OBJC_TYPE(RTCAudioBuffer) *)audioBuffer { +- (void)audioProcessingProcess:(LKRTCAudioBuffer *)audioBuffer { os_unfair_lock_lock(&_lock); for (id processor in _processors) { [processor audioProcessingProcess:audioBuffer]; } - for (id renderer in _renderers) { + for (id renderer in _renderers) { [renderer renderPCMBuffer:[self toPCMBuffer:audioBuffer]]; } os_unfair_lock_unlock(&_lock); diff --git a/ios/LKAudioProcessingManager.m b/ios/LKAudioProcessingManager.m index 083fa778..cd20309d 100644 --- a/ios/LKAudioProcessingManager.m +++ b/ios/LKAudioProcessingManager.m @@ -14,7 +14,7 @@ + (instancetype)sharedInstance { - (instancetype)init { if (self = [super init]) { - _audioProcessingModule = [[RTCDefaultAudioProcessingModule alloc] init]; + _audioProcessingModule = [[LKRTCDefaultAudioProcessingModule alloc] init]; _capturePostProcessingAdapter = [[LKAudioProcessingAdapter alloc] init]; _renderPreProcessingAdapter = [[LKAudioProcessingAdapter alloc] init]; _audioProcessingModule.capturePostProcessingDelegate = _capturePostProcessingAdapter; @@ -23,19 +23,19 @@ - (instancetype)init { return self; } -- (void)addLocalAudioRenderer:(nonnull id)renderer { +- (void)addLocalAudioRenderer:(nonnull id)renderer { [_capturePostProcessingAdapter addAudioRenderer:renderer]; } -- (void)removeLocalAudioRenderer:(nonnull id)renderer { +- (void)removeLocalAudioRenderer:(nonnull id)renderer { [_capturePostProcessingAdapter removeAudioRenderer:renderer]; } -- (void)addRemoteAudioRenderer:(nonnull id)renderer { +- (void)addRemoteAudioRenderer:(nonnull id)renderer { [_renderPreProcessingAdapter addAudioRenderer:renderer]; } -- (void)removeRemoteAudioRenderer:(nonnull id)renderer { +- (void)removeRemoteAudioRenderer:(nonnull id)renderer { [_renderPreProcessingAdapter removeAudioRenderer:renderer]; } diff --git a/ios/LiveKitReactNativeModule.swift b/ios/LiveKitReactNativeModule.swift index e85be6e1..435b339b 100644 --- a/ios/LiveKitReactNativeModule.swift +++ b/ios/LiveKitReactNativeModule.swift @@ -27,7 +27,7 @@ public class LivekitReactNativeModule: RCTEventEmitter { @objc public override init() { super.init() - let config = RTCAudioSessionConfiguration() + let config = LKRTCAudioSessionConfiguration() config.category = AVAudioSession.Category.playAndRecord.rawValue // Gated on compiler version (not iOS deploy target): .allowBluetoothHFP // is only declared in the Xcode 26 / Swift 6.2 SDK, which replaces the @@ -39,7 +39,7 @@ public class LivekitReactNativeModule: RCTEventEmitter { #endif config.mode = AVAudioSession.Mode.videoChat.rawValue - RTCAudioSessionConfiguration.setWebRTC(config) + LKRTCAudioSessionConfiguration.setWebRTC(config) } @objc @@ -49,8 +49,8 @@ public class LivekitReactNativeModule: RCTEventEmitter { @objc public static func setup() { - let videoEncoderFactory = RTCDefaultVideoEncoderFactory() - let simulcastVideoEncoderFactory = RTCVideoEncoderFactorySimulcast(primary: videoEncoderFactory, fallback: videoEncoderFactory) + let videoEncoderFactory = LKRTCDefaultVideoEncoderFactory() + let simulcastVideoEncoderFactory = LKRTCVideoEncoderFactorySimulcast(primary: videoEncoderFactory, fallback: videoEncoderFactory) let options = WebRTCModuleOptions.sharedInstance() options.videoEncoderFactory = simulcastVideoEncoderFactory options.audioProcessingModule = LKAudioProcessingManager.sharedInstance().audioProcessingModule @@ -65,7 +65,7 @@ public class LivekitReactNativeModule: RCTEventEmitter { let defaultOutput = iOSConfig["defaultOutput"] as? String ?? "speaker" - let rtcConfig = RTCAudioSessionConfiguration() + let rtcConfig = LKRTCAudioSessionConfiguration() rtcConfig.category = AVAudioSession.Category.playAndRecord.rawValue if (defaultOutput == "earpiece") { @@ -75,12 +75,12 @@ public class LivekitReactNativeModule: RCTEventEmitter { rtcConfig.categoryOptions = [.allowAirPlay, .allowBluetooth, .allowBluetoothA2DP, .defaultToSpeaker] rtcConfig.mode = AVAudioSession.Mode.videoChat.rawValue } - RTCAudioSessionConfiguration.setWebRTC(rtcConfig) + LKRTCAudioSessionConfiguration.setWebRTC(rtcConfig) } @objc(startAudioSession:withRejecter:) public func startAudioSession(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { - let session = RTCAudioSession.sharedInstance() + let session = LKRTCAudioSession.sharedInstance() session.lockForConfiguration() defer { session.unlockForConfiguration() @@ -96,7 +96,7 @@ public class LivekitReactNativeModule: RCTEventEmitter { @objc(stopAudioSession:withRejecter:) public func stopAudioSession(resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { - let session = RTCAudioSession.sharedInstance() + let session = LKRTCAudioSession.sharedInstance() session.lockForConfiguration() defer { session.unlockForConfiguration() @@ -149,8 +149,8 @@ public class LivekitReactNativeModule: RCTEventEmitter { @objc(setAppleAudioConfiguration:withResolver:withRejecter:) public func setAppleAudioConfiguration(_ configuration: NSDictionary, resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) { - let session = RTCAudioSession.sharedInstance() - let config = RTCAudioSessionConfiguration.webRTC() + let session = LKRTCAudioSession.sharedInstance() + let config = LKRTCAudioSessionConfiguration.webRTC() let appleAudioCategory = configuration["audioCategory"] as? String let appleAudioCategoryOptions = configuration["audioCategoryOptions"] as? [String] diff --git a/ios/LivekitReactNative.m b/ios/LivekitReactNative.m index b857eca6..ea7b21eb 100644 --- a/ios/LivekitReactNative.m +++ b/ios/LivekitReactNative.m @@ -6,8 +6,8 @@ @implementation LivekitReactNative +(void)setup { - RTCDefaultVideoEncoderFactory *videoEncoderFactory = [[RTCDefaultVideoEncoderFactory alloc] init]; - RTCVideoEncoderFactorySimulcast *simulcastVideoEncoderFactory = [[RTCVideoEncoderFactorySimulcast alloc] initWithPrimary:videoEncoderFactory fallback:videoEncoderFactory]; + LKRTCDefaultVideoEncoderFactory *videoEncoderFactory = [[LKRTCDefaultVideoEncoderFactory alloc] init]; + LKRTCVideoEncoderFactorySimulcast *simulcastVideoEncoderFactory = [[LKRTCVideoEncoderFactorySimulcast alloc] initWithPrimary:videoEncoderFactory fallback:videoEncoderFactory]; WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance]; options.videoEncoderFactory = simulcastVideoEncoderFactory; options.audioProcessingModule = LKAudioProcessingManager.sharedInstance.audioProcessingModule; diff --git a/ios/audio/AudioProcessing.swift b/ios/audio/AudioProcessing.swift index f5cc4ed3..19910d85 100644 --- a/ios/audio/AudioProcessing.swift +++ b/ios/audio/AudioProcessing.swift @@ -25,7 +25,7 @@ public struct AudioLevel { public let peak: Float } -public extension RTCAudioBuffer { +public extension LKRTCAudioBuffer { /// Convert to AVAudioPCMBuffer Int16 format. @objc func toAVAudioPCMBuffer() -> AVAudioPCMBuffer? { diff --git a/ios/audio/AudioRendererManager.swift b/ios/audio/AudioRendererManager.swift index fc7bab49..8ee80a52 100644 --- a/ios/audio/AudioRendererManager.swift +++ b/ios/audio/AudioRendererManager.swift @@ -3,14 +3,14 @@ import livekit_react_native_webrtc @objc public class AudioRendererManager: NSObject { private let bridge: RCTBridge - public private(set) var renderers: [String: RTCAudioRenderer] = [:] + public private(set) var renderers: [String: LKRTCAudioRenderer] = [:] init(bridge: RCTBridge) { self.bridge = bridge } @objc - public func registerRenderer(_ audioRenderer: RTCAudioRenderer) -> String { + public func registerRenderer(_ audioRenderer: LKRTCAudioRenderer) -> String { let reactTag = NSUUID().uuidString self.renderers[reactTag] = audioRenderer return reactTag @@ -22,14 +22,14 @@ public class AudioRendererManager: NSObject { } @objc - public func unregisterRenderer(_ audioRenderer: RTCAudioRenderer) { + public func unregisterRenderer(_ audioRenderer: LKRTCAudioRenderer) { self.renderers = self.renderers.filter({ $0.value !== audioRenderer }) } @objc - public func attach(renderer: RTCAudioRenderer, pcId: NSNumber, trackId: String) { + public func attach(renderer: LKRTCAudioRenderer, pcId: NSNumber, trackId: String) { let webrtcModule = self.bridge.module(for: WebRTCModule.self) as! WebRTCModule - guard let track = webrtcModule.track(forId: trackId, pcId: pcId) as? RTCAudioTrack + guard let track = webrtcModule.track(forId: trackId, pcId: pcId) as? LKRTCAudioTrack else { lklog("couldn't find audio track: pcId: \(pcId), trackId: \(trackId)") return @@ -54,9 +54,9 @@ public class AudioRendererManager: NSObject { } @objc - public func detach(renderer: RTCAudioRenderer, pcId: NSNumber, trackId: String) { + public func detach(renderer: LKRTCAudioRenderer, pcId: NSNumber, trackId: String) { let webrtcModule = self.bridge.module(for: WebRTCModule.self) as! WebRTCModule - guard let track = webrtcModule.track(forId: trackId, pcId: pcId) as? RTCAudioTrack + guard let track = webrtcModule.track(forId: trackId, pcId: pcId) as? LKRTCAudioTrack else { lklog("couldn't find audio track: pcId: \(pcId), trackId: \(trackId)") return diff --git a/ios/audio/AudioSinkRenderer.swift b/ios/audio/AudioSinkRenderer.swift index c5d99c6a..ded72d8c 100644 --- a/ios/audio/AudioSinkRenderer.swift +++ b/ios/audio/AudioSinkRenderer.swift @@ -31,7 +31,7 @@ public class AudioSinkRenderer: BaseAudioSinkRenderer { } } -public class BaseAudioSinkRenderer: NSObject, RTCAudioRenderer { +public class BaseAudioSinkRenderer: NSObject, LKRTCAudioRenderer { public override init() { super.init() diff --git a/ios/audio/MultibandVolumeAudioRenderer.swift b/ios/audio/MultibandVolumeAudioRenderer.swift index 64f9ccf6..8247415f 100644 --- a/ios/audio/MultibandVolumeAudioRenderer.swift +++ b/ios/audio/MultibandVolumeAudioRenderer.swift @@ -34,7 +34,7 @@ public class MultibandVolumeAudioRenderer: BaseMultibandVolumeAudioRenderer { } -public class BaseMultibandVolumeAudioRenderer: NSObject, RTCAudioRenderer { +public class BaseMultibandVolumeAudioRenderer: NSObject, LKRTCAudioRenderer { private let frameInterval: Int private var skippedFrames = 0 private let audioProcessor: AudioVisualizeProcessor diff --git a/ios/audio/VolumeAudioRenderer.swift b/ios/audio/VolumeAudioRenderer.swift index f2506f28..dca4fabd 100644 --- a/ios/audio/VolumeAudioRenderer.swift +++ b/ios/audio/VolumeAudioRenderer.swift @@ -25,7 +25,7 @@ public class VolumeAudioRenderer: BaseVolumeAudioRenderer { } } -public class BaseVolumeAudioRenderer: NSObject, RTCAudioRenderer { +public class BaseVolumeAudioRenderer: NSObject, LKRTCAudioRenderer { private let frameInterval: Int private var skippedFrames = 0 public init(intervalMs: Double = 30) { From 419e1f51417b7d7c8c555f9092137e406561110c Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed, 9 Sep 2026 19:52:15 +0800 Subject: [PATCH 2/3] docs: no Podfile source changes needed LiveKitWebRTC 144.7559.15 is published on the CocoaPods trunk, so consumers need no extra source lines in their Podfile. Drop the source instructions from the changeset and revert the README, example, and CI Podfiles to their state on main. --- .changeset/prefixed-webrtc-symbols.md | 7 ------- README.md | 10 ---------- ci/ios/Podfile | 3 --- example/ios/Podfile | 3 --- 4 files changed, 23 deletions(-) diff --git a/.changeset/prefixed-webrtc-symbols.md b/.changeset/prefixed-webrtc-symbols.md index 4e077ed9..4ccf551c 100644 --- a/.changeset/prefixed-webrtc-symbols.md +++ b/.changeset/prefixed-webrtc-symbols.md @@ -4,11 +4,4 @@ Move to the prefixed WebRTC builds: `io.github.webrtc-sdk:android-prefixed` on Android and the `LiveKitWebRTC` pod on iOS. -iOS apps must add the LiveKit podspec source to their `Podfile`, since `LiveKitWebRTC` is not published on the CocoaPods trunk: - -```ruby -source 'https://cdn.cocoapods.org/' -source 'https://github.com/livekit/podspecs.git' -``` - Apps that only use the JavaScript API need no other changes. Native integrations must migrate to the prefixed symbols: `org.webrtc.*` becomes `livekit.org.webrtc.*` on Android, and libwebrtc Objective-C types gain an `LK` prefix on iOS (`RTCAudioRenderer` becomes `LKRTCAudioRenderer`, `RTCAudioBuffer` becomes `LKRTCAudioBuffer`, and so on). Custom `-keep class org.webrtc.**` ProGuard rules must be updated to `livekit.org.webrtc.**`. diff --git a/README.md b/README.md index bb72d852..38653824 100644 --- a/README.md +++ b/README.md @@ -37,16 +37,6 @@ This library depends on `@livekit/react-native-webrtc`, which has additional ins - [iOS Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/iOSInstallation.md) - [Android Installation Guide](https://github.com/livekit/react-native-webrtc/blob/master/Documentation/AndroidInstallation.md) -On iOS, the underlying `LiveKitWebRTC` pod is published from -[livekit/podspecs](https://github.com/livekit/podspecs) rather than the CocoaPods trunk, so add both -sources at the top of your `Podfile`. Both lines are required: declaring any source disables the -implicit trunk default, and the rest of your pods would no longer resolve. - -```ruby -source 'https://cdn.cocoapods.org/' -source 'https://github.com/livekit/podspecs.git' -``` - --- Once the `@livekit/react-native-webrtc` dependency is installed, one last step is needed to finish the installation: diff --git a/ci/ios/Podfile b/ci/ios/Podfile index a026024c..3e2df095 100644 --- a/ci/ios/Podfile +++ b/ci/ios/Podfile @@ -1,6 +1,3 @@ -source 'https://cdn.cocoapods.org/' -source 'https://github.com/livekit/podspecs.git' - # Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( diff --git a/example/ios/Podfile b/example/ios/Podfile index a3bb4ae0..4d8a7930 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,6 +1,3 @@ -source 'https://cdn.cocoapods.org/' -source 'https://github.com/livekit/podspecs.git' - # Resolve react_native_pods.rb with node to allow for hoisting require Pod::Executable.execute_command('node', ['-p', 'require.resolve( From 9fd387c0e3ba2f95462db6c0be0cdf8466e715dd Mon Sep 17 00:00:00 2001 From: Hiroshi Horie <548776+hiroshihorie@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:55:42 +0800 Subject: [PATCH 3/3] chore: regenerate example Podfile.lock against the trunk pod LiveKitWebRTC now resolves from the CocoaPods trunk, so the lockfile no longer references the podspecs source and its checksum matches the reverted Podfile. --- example/ios/Podfile.lock | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 43ea8632..17b6a375 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2617,9 +2617,8 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - https://github.com/livekit/podspecs.git: - - LiveKitWebRTC trunk: + - LiveKitWebRTC - SocketRocket EXTERNAL SOURCES: @@ -2793,8 +2792,8 @@ SPEC CHECKSUMS: hermes-engine: 273e30e7fb618279934b0b95ffab60ecedb7acf5 livekit-react-native: 27001a5d9454cc8d27894317425aa511801154e2 livekit-react-native-webrtc: 8ac4a8c004158ec95db235b6c6a818dee66df0a4 - LiveKitWebRTC: c055d3954f3c3f17f0e327f72b8e91a6c3ebcc47 - RCT-Folly: 59ec0ac1f2f39672a0c6e6cecdd39383b764646f + LiveKitWebRTC: 6abc86e190722e223fc870284547b6f229288c46 + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 RCTDeprecation: f17e2ebc07876ca9ab8eb6e4b0a4e4647497ae3a RCTRequired: e2c574c1b45231f7efb0834936bd609d75072b63 RCTTypeSafety: c693294e3993056955c3010eb1ebc574f1fcded6 @@ -2866,6 +2865,6 @@ SPEC CHECKSUMS: SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 Yoga: 689c8e04277f3ad631e60fe2a08e41d411daf8eb -PODFILE CHECKSUM: 841abb8b2992cf16bb758bde8cf7f8cdbfb22695 +PODFILE CHECKSUM: a921a659e37cd7dfb12da519493e10c9f38400a1 -COCOAPODS: 1.16.2 +COCOAPODS: 1.17.0