Live video on the AT Protocol
at eli/multitesting 210 lines 6.4 kB view raw
1import RNWebRTCPlugin from "@config-plugins/react-native-webrtc"; 2import { ExpoConfig } from "expo/config"; 3import { 4 ConfigPlugin, 5 IOSConfig, 6 withAppDelegate, 7 withMainApplication, 8 withXcodeProject, 9} from "expo/config-plugins"; 10import { resolve } from "path"; 11 12const buildError = (message: string) => { 13 if (process.env.SP_SKIP_CODEMODE_ERRORS !== "true") { 14 throw new Error(`@streamplace/config-native-webrtc ${message}`); 15 } else { 16 console.error( 17 `@streamplace/config-native-webrtc ${message}, skipping because SP_SKIP_CODEMODE_ERRORS=true`, 18 ); 19 } 20}; 21 22// https://github.com/react-native-webrtc/react-native-webrtc/blob/19ca31d4b77d149a659ee037fae54861a2d90a73/Documentation/AndroidInstallation.md#set-audio-category-output-to-media 23// look, i'm as upset about this as you are 24const androidApplicationReplacements = [ 25 { 26 from: "class MainApplication : Application(), ReactApplication {", 27 to: ` 28import com.oney.WebRTCModule.WebRTCModuleOptions 29import android.media.AudioAttributes 30import org.webrtc.audio.JavaAudioDeviceModule 31 32class MainApplication : Application(), ReactApplication {`, 33 }, 34 { 35 from: "override fun onCreate() {", 36 to: ` 37 override fun onCreate() { 38 // append this before WebRTCModule initializes 39 val options = WebRTCModuleOptions.getInstance() 40 val audioAttributes = AudioAttributes.Builder() 41 .setUsage(AudioAttributes.USAGE_MEDIA) 42 .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) 43 .build() 44 options.audioDeviceModule = JavaAudioDeviceModule.builder(this) 45 .setAudioAttributes(audioAttributes) 46 .setUseStereoInput(true) 47 .setUseStereoOutput(true) 48 .createAudioDeviceModule() 49`, 50 }, 51]; 52 53export const withWorkingAndroidWebRTCAudio: ConfigPlugin = (configOuter) => { 54 return withMainApplication(configOuter, (config) => { 55 let stringContents: string = config.modResults.contents; 56 57 for (const { from, to } of androidApplicationReplacements) { 58 stringContents = stringContents.replace(from, to); 59 } 60 if (stringContents === config.modResults.contents) { 61 buildError("android codemod failed to apply"); 62 } 63 64 config.modResults.contents = stringContents; 65 66 return config; 67 }); 68}; 69 70const iosDelegateReplacements = [ 71 // Objective-C Version 72 { 73 from: "#import <React/RCTLinkingManager.h>", 74 to: (config) => ` 75#import <React/RCTLinkingManager.h> 76#import <WebRTC/WebRTC.h> 77#import "CaptureController.h" 78#import "CapturerEventsDelegate.h" 79#import "DataChannelWrapper.h" 80#import "RCTConvert+WebRTC.h" 81#import "RTCMediaStreamTrack+React.h" 82#import "RTCVideoViewManager.h" 83#import "ScreenCaptureController.h" 84#import "ScreenCapturePickerViewManager.h" 85#import "ScreenCapturer.h" 86#import "SerializeUtils.h" 87#import "SocketConnection.h" 88#import "TrackCapturerEventsEmitter.h" 89#import "VideoCaptureController.h" 90#import "WebRTCModule+RTCDataChannel.h" 91#import "WebRTCModule+RTCMediaStream.h" 92#import "WebRTCModule+RTCPeerConnection.h" 93#import "WebRTCModule+VideoTrackAdapter.h" 94#import "WebRTCModule.h" 95#import "WebRTCModuleOptions.h" 96#import "ExpoModulesCore-Swift.h" 97#import "${config.name.replaceAll(" ", "")}-Swift.h" 98`, 99 }, 100 { 101 from: " self.initialProps = @{};", 102 to: () => ` 103 self.initialProps = @{}; 104 ////RTC PATCH//// 105 RTCAudioSessionConfiguration* config = [RTCAudioSessionConfiguration webRTCConfiguration]; 106 107 AVAudioSession * session = [AVAudioSession sharedInstance]; 108 // Set audio to use phone speaker instead of headset speaker 109 [session setCategory:AVAudioSessionCategoryPlayAndRecord 110 withOptions:AVAudioSessionCategoryOptionDefaultToSpeaker | AVAudioSessionCategoryOptionAllowBluetooth 111 error:nil]; 112 [session setActive:YES error:nil]; 113 114 id<RTCAudioDevice> device; 115 device = [[AUAudioUnitRTCAudioDevice alloc] init]; 116 117 WebRTCModuleOptions *options = [WebRTCModuleOptions sharedInstance]; 118 options.loggingSeverity = RTCLoggingSeverityWarning; 119 options.audioDevice = device; 120 // Enable stereo audio 121 options.enableStereoOutput = YES; 122 ////END RTC PATCH//// 123 `, 124 }, 125 // Swift Version 126 { 127 from: " let delegate = ReactNativeDelegate()", 128 to: () => ` 129 // WebRTC Configuration 130 let config = RTCAudioSessionConfiguration.webRTC() 131 132 let session = AVAudioSession.sharedInstance() 133 do { 134 try session.setCategory(.playAndRecord, 135 options: [.defaultToSpeaker, .allowBluetooth]) 136 try session.setActive(true) 137 } catch { 138 print("Failed to configure audio session: \(error)") 139 } 140 141 let device = AUAudioUnitRTCAudioDevice() 142 143 let options = WebRTCModuleOptions.sharedInstance() 144 options.loggingSeverity = .warning 145 options.audioDevice = device 146 // End WebRTC Configuration 147 148 let delegate = ReactNativeDelegate() 149 `, 150 }, 151 { 152 from: "import ReactAppDependencyProvider", 153 to: () => ` 154import ReactAppDependencyProvider 155import WebRTC 156import react_native_webrtc 157import AVFoundation 158 `, 159 }, 160]; 161 162const withWorkingIOSWebRTCAudio: ConfigPlugin = (config) => { 163 const files = [ 164 "AUAudioUnitRTCAudioDevice.swift", 165 "AudioSessionHandler.swift", 166 "SimpleAudioConverter.swift", 167 "Utils.swift", 168 ]; 169 170 let called = false; 171 // modify the app delegate to make use of the CustomRTCAudioDevice 172 config = withAppDelegate(config, (config) => { 173 let stringContents: string = config.modResults.contents; 174 175 for (const { from, to } of iosDelegateReplacements) { 176 stringContents = stringContents.replace(from, to(config)); 177 } 178 if (stringContents === config.modResults.contents) { 179 buildError("ios codemod failed to change anything, aborting"); 180 } 181 182 config.modResults.contents = stringContents; 183 called = true; 184 185 return config; 186 }); 187 188 // add the CustomRTCAudioDevice files to the xcode project 189 config = withXcodeProject(config, (config) => { 190 const rtc = require.resolve("rtcaudiodevice"); 191 for (const file of files) { 192 IOSConfig.XcodeUtils.addBuildSourceFileToGroup({ 193 filepath: resolve(rtc, "..", "CustomRTCAudioDevice", file), 194 groupName: config.name, 195 project: config.modResults, 196 }); 197 } 198 199 return config; 200 }); 201 202 return config; 203}; 204 205export default function withStreamplaceReactNativeWebRTC(config: ExpoConfig) { 206 config = RNWebRTCPlugin(config); 207 config = withWorkingAndroidWebRTCAudio(config); 208 config = withWorkingIOSWebRTCAudio(config); 209 return config; 210}