### Install project dependencies using CocoaPods Source: https://github.com/shengwang-community/api-examples/blob/main/iOS/APIExample-OC/README.md This command installs the necessary dependencies for the project using CocoaPods. Ensure CocoaPods is installed on your system before running this command. ```shell pod install ``` -------------------------------- ### Configure and Start RTMP Streaming (Java) Source: https://context7.com/shengwang-community/api-examples/llms.txt Configures live transcoding settings, including video, audio, layout, watermarks, and background images, then starts the RTMP streaming. Requires Agora SDK. Outputs RTMP stream to a specified URL. ```java // Android - RTMPStreaming.java import io.agora.rtc2.live.*; public class RTMPStreamingExample { private RtcEngine engine; private String rtmpUrl = "rtmp://live.example.com/live/stream123"; private void startRTMPStreaming(String channelName) { // 1. Configure live transcoding LiveTranscoding transcoding = new LiveTranscoding(); // Video settings transcoding.width = 1280; transcoding.height = 720; transcoding.videoBitrate = 2000; // kbps transcoding.videoFramerate = 30; transcoding.videoCodecProfile = LiveTranscoding.VideoCodecProfileType.HIGH; transcoding.videoGop = 30; // Group of pictures // Audio settings transcoding.audioSampleRate = LiveTranscoding.AudioSampleRateType.TYPE_48000; transcoding.audioBitrate = 128; // kbps transcoding.audioChannels = 2; // Stereo transcoding.audioCodecProfile = LiveTranscoding.AudioCodecProfileType.AAC_LC; // Layout settings transcoding.backgroundColor = 0x000000; // Black background transcoding.userCount = 1; // Number of users in layout // Configure user layout LiveTranscoding.TranscodingUser user = new LiveTranscoding.TranscodingUser(); user.uid = 0; // Local user user.x = 0; user.y = 0; user.width = transcoding.width; user.height = transcoding.height; user.zOrder = 0; // Layer order user.alpha = 1.0; // Opacity user.audioChannel = 0; ArrayList users = new ArrayList<>(); users.add(user); transcoding.setUsers(users); // Optional: Add watermark AgoraImage watermark = new AgoraImage(); watermark.url = "https://example.com/logo.png"; watermark.x = transcoding.width - 200; // Top-right corner watermark.y = 20; watermark.width = 180; watermark.height = 60; watermark.alpha = 0.8; transcoding.setWatermark(watermark); // Optional: Add background image AgoraImage background = new AgoraImage(); background.url = "https://example.com/background.jpg"; background.x = 0; background.y = 0; background.width = transcoding.width; background.height = transcoding.height; transcoding.setBackgroundImage(background); // 2. Set live transcoding configuration int result = engine.setLiveTranscoding(transcoding); if (result != 0) { Log.e(TAG, "setLiveTranscoding failed: " + result); return; } // 3. Add RTMP stream URL result = engine.addPublishStreamUrl(rtmpUrl, true); // true = enable transcoding if (result != 0) { Log.e(TAG, "addPublishStreamUrl failed: " + result); } } // ... other methods and event handler ... } ``` -------------------------------- ### Define App ID and Token (C++) Source: https://github.com/shengwang-community/api-examples/blob/main/windows/README.md This snippet shows how to define the application ID and access token using preprocessor macros in C++. These are essential for authenticating with the Agora services. ```cpp #define APP_ID _T("Your App ID") #define APP_TOKEN _T("Your Token") ``` -------------------------------- ### Configure Agora App ID and Certificate in Swift Source: https://github.com/shengwang-community/api-examples/blob/main/macOS/README.md Swift code snippet to configure Agora App ID and Certificate within the KeyCenter struct. Requires obtaining these values from the Agora dashboard. ```swift /** Agora assigns App IDs to app developers to identify projects and organizations. If you have multiple completely separate apps in your organization, for example built by different teams, you should use different App IDs. If applications need to communicate with each other, they should use the same App ID. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project, then the APP ID can be found in the project detail page. */ static let AppId: String = <# YOUR APPID#> /** Agora provides App certificate to generate Token. You can deploy and generate a token on your server, or use the console to generate a temporary token. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project with the App Certificate enabled, then the APP Certificate can be found in the project detail page.If the project does not have certificates enabled, leave this field blank. PS: It is unsafe to place the App Certificate on the client side, it is recommended to place it on the server side to ensure that the App Certificate is not leaked. */ static var Certificate: String? = <#YOUR Certificate#> ``` -------------------------------- ### Configure App ID and Certificate in KeyCenter.m Source: https://github.com/shengwang-community/api-examples/blob/main/iOS/APIExample-OC/README.md This Objective-C snippet shows how to configure the App ID and Certificate in the KeyCenter.m file. Replace placeholders with your actual App ID and Certificate from the Agora dashboard. ```Objective-C static NSString * const APPID = <# YOUR APPID#> static NSString * const Certificate = <#YOUR Certificate#> ``` -------------------------------- ### Configure Agora App ID and Token (Swift) Source: https://github.com/shengwang-community/api-examples/blob/main/iOS/APIExample/README.md This snippet shows how to configure the App Id and Access Token within the `KeyCenter.swift` file in the Xcode workspace. Provide your actual App Id and temporary Access Token generated from the Agora dashboard. ```swift /** Agora assigns App IDs to app developers to identify projects and organizations. If you have multiple completely separate apps in your organization, for example built by different teams, you should use different App IDs. If applications need to communicate with each other, they should use the same App ID. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project, then the APP ID can be found in the project detail page. */ static let AppId: String = <# YOUR APPID#> /** Agora provides App certificate to generate Token. You can deploy and generate a token on your server, or use the console to generate a temporary token. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project with the App Certificate enabled, then the APP Certificate can be found in the project detail page.If the project does not have certificates enabled, leave this field blank. PS: It is unsafe to place the App Certificate on the client side, it is recommended to place it on the server side to ensure that the App Certificate is not leaked. */ static var Certificate: String? = <#YOUR Certificate#> ``` -------------------------------- ### App ID Configuration (INI) (C++) Source: https://github.com/shengwang-community/api-examples/blob/main/windows/README.md This snippet illustrates an alternative method for configuring the App ID by creating an INI file. The application reads the App ID from this file, which is located in the Debug/Release directory. ```ini [AppID] #AppID=xxxxxxxxxxxxxxxxxxx ``` -------------------------------- ### Configure App ID and Token in Swift Source: https://github.com/shengwang-community/api-examples/blob/main/iOS/APIExample-Audio/README.md This Swift code snippet shows how to configure the Agora App ID and temporary Access Token in the KeyCenter.swift file. The App ID identifies your project while the token provides temporary access. ```Swift /** Agora assigns App IDs to app developers to identify projects and organizations. If you have multiple completely separate apps in your organization, for example built by different teams, you should use different App IDs. If applications need to communicate with each other, they should use the same App ID. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project, then the APP ID can be found in the project detail page. */ static let AppId: String = <# YOUR APPID#> /** Agora provides App certificate to generate Token. You can deploy and generate a token on your server, or use the console to generate a temporary token. In order to get the APP ID, you can open the agora console (https://console.agora.io/) to create a project with the App Certificate enabled, then the APP Certificate can be found in the project detail page.If the project does not have certificates enabled, leave this field blank. PS: It is unsafe to place the App Certificate on the client side, it is recommended to place it on the server side to ensure that the App Certificate is not leaked. */ static var Certificate: String? = <#YOUR Certificate#> ``` -------------------------------- ### Configure Agora App ID and Certificate in Android Source: https://github.com/shengwang-community/api-examples/blob/main/Android/APIExample/README.md This snippet demonstrates how to set up the Agora App ID and App Certificate in an Android project. Ensure to replace placeholder values with actual credentials from the Agora Dashboard. The App Certificate can be left blank if security tokens are not enabled. ```xml // Agora APP ID. YOUR APP ID // Agora APP Certificate. If the project does not have certificates enabled, leave this field blank. // PS:It is unsafe to place the App Certificate on the client side, it is recommended to place it on the server side to ensure that the App Certificate is not leaked. YOUR APP CERTIFICATE ``` -------------------------------- ### Configure Agora App ID and Certificate in Android Source: https://github.com/shengwang-community/api-examples/blob/main/Android/APIExample-Compose/README.md This configuration snippet shows how to set your Agora App ID and App Certificate in the `local.properties` file for the Android sample application. Ensure you replace `YOUR APP ID` and `YOUR APP CERTIFICATE` with your actual credentials obtained from the Agora dashboard. The App Certificate can be left blank if your project does not use security tokens. ```properties AGORA_APP_ID=YOUR APP ID AGORA_APP_CERT=YOUR APP CERTIFICATE ``` -------------------------------- ### Update RTMP Transcoding Layout (Java) Source: https://context7.com/shengwang-community/api-examples/llms.txt Updates the RTMP live transcoding layout, typically when a new user joins the channel. This example shows a split-screen layout for local and remote users. Depends on the Agora SDK. Modifies the existing stream output. ```java // Android - RTMPStreaming.java (continued) private void updateTranscodingLayout(int remoteUid) { // Update layout when new user joins LiveTranscoding transcoding = new LiveTranscoding(); transcoding.width = 1280; transcoding.height = 720; transcoding.videoBitrate = 2000; transcoding.videoFramerate = 30; transcoding.videoGop = 30; transcoding.audioSampleRate = LiveTranscoding.AudioSampleRateType.TYPE_48000; transcoding.audioBitrate = 128; transcoding.audioChannels = 2; transcoding.userCount = 2; // Now 2 users // Layout: Split screen ArrayList users = new ArrayList<>(); // Local user (left half) LiveTranscoding.TranscodingUser localUser = new LiveTranscoding.TranscodingUser(); localUser.uid = 0; localUser.x = 0; localUser.y = 0; localUser.width = transcoding.width / 2; localUser.height = transcoding.height; localUser.zOrder = 0; localUser.alpha = 1.0; users.add(localUser); // Remote user (right half) LiveTranscoding.TranscodingUser remoteUser = new LiveTranscoding.TranscodingUser(); remoteUser.uid = remoteUid; remoteUser.x = transcoding.width / 2; remoteUser.y = 0; remoteUser.width = transcoding.width / 2; remoteUser.height = transcoding.height; remoteUser.zOrder = 0; remoteUser.alpha = 1.0; users.add(remoteUser); transcoding.setUsers(users); // Update transcoding engine.setLiveTranscoding(transcoding); } ``` -------------------------------- ### Android XML String Configuration for Agora Credentials Source: https://github.com/shengwang-community/api-examples/blob/main/Android/APIExample-Audio/README.md This snippet shows how to configure Agora API credentials within an Android application's string resources. It requires updating placeholders for App ID, App Certificate, and Access Token. The App Certificate should ideally be handled server-side for security. ```xml YOUR APP ID // assign token and certificate to null if you have not enabled app certificate YOUR APP CERTIFICATE // assign token and certificate to null if you have not enabled app certificate or you have set the certificate above. // PS: It is unsafe to place the App Certificate on the client side, it is recommended to place it on the server side to ensure that the App Certificate is not leaked. YOUR ACCESS TOKEN ``` -------------------------------- ### Android Screen Sharing with Agora SDK Source: https://context7.com/shengwang-community/api-examples/llms.txt This Java code snippet illustrates how to implement screen sharing functionality in an Android application using the Agora SDK. It covers requesting screen capture permission via MediaProjectionManager, configuring ScreenCaptureParameters for video and audio, starting the screen capture, and updating channel media options to publish the screen track. It also includes methods to stop screen sharing and dynamically update capture parameters. ```java import android.app.Activity; import android.content.Context; import android.content.Intent; import android.media.projection.MediaProjectionManager; import io.agora.rtc2.ScreenCaptureParameters; import io.agora.rtc2.video.VideoEncoderConfiguration; public class ScreenSharingExample extends Fragment { private RtcEngine engine; private static final int SCREEN_CAPTURE_REQUEST_CODE = 1001; private MediaProjectionManager projectionManager; @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); projectionManager = (MediaProjectionManager) requireContext() .getSystemService(Context.MEDIA_PROJECTION_SERVICE); } private void startScreenSharing() { // 1. Request screen capture permission Intent intent = projectionManager.createScreenCaptureIntent(); startActivityForResult(intent, SCREEN_CAPTURE_REQUEST_CODE); } @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == SCREEN_CAPTURE_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK && data != null) { // Permission granted, start screen capture startScreenCapture(resultCode, data); } else { showToast("Screen capture permission denied"); } } } private void startScreenCapture(int resultCode, Intent data) { // 2. Configure screen capture parameters ScreenCaptureParameters parameters = new ScreenCaptureParameters(); // Video encoding parameters parameters.videoCaptureParameters = new ScreenCaptureParameters.VideoCaptureParameters(); parameters.videoCaptureParameters.width = 1280; parameters.videoCaptureParameters.height = 720; parameters.videoCaptureParameters.framerate = 15; parameters.videoCaptureParameters.bitrate = 2000; // kbps parameters.videoCaptureParameters.contentHint = ScreenCaptureParameters.VideoCaptureParameters.CONTENT_HINT_MOTION; // or CONTENT_HINT_DETAILS // Audio capture (optional) parameters.captureAudio = true; parameters.audioCaptureParameters = new ScreenCaptureParameters.AudioCaptureParameters(); parameters.audioCaptureParameters.sampleRate = 48000; parameters.audioCaptureParameters.channels = 2; parameters.audioCaptureParameters.captureSignalVolume = 100; // 3. Start screen capture int result = engine.startScreenCapture(resultCode, data, parameters); if (result != 0) { Log.e(TAG, "startScreenCapture failed: " + result); showToast("Failed to start screen sharing"); return; } // 4. Update channel options to publish screen track ChannelMediaOptions options = new ChannelMediaOptions(); options.publishScreenTrack = true; options.publishScreenCaptureAudio = true; options.publishScreenCaptureVideo = true; options.publishCameraTrack = false; // Stop camera options.publishMicrophoneTrack = true; // Keep microphone engine.updateChannelMediaOptions(options); Log.i(TAG, "Screen sharing started"); showToast("Screen sharing active"); } private void stopScreenSharing() { // Stop screen capture int result = engine.stopScreenCapture(); if (result != 0) { Log.e(TAG, "stopScreenCapture failed: " + result); return; } // Switch back to camera ChannelMediaOptions options = new ChannelMediaOptions(); options.publishScreenTrack = false; options.publishScreenCaptureAudio = false; options.publishScreenCaptureVideo = false; options.publishCameraTrack = true; options.publishMicrophoneTrack = true; engine.updateChannelMediaOptions(options); showToast("Screen sharing stopped"); } private void updateScreenCaptureParameters() { // Dynamically update capture parameters ScreenCaptureParameters parameters = new ScreenCaptureParameters(); parameters.videoCaptureParameters = new ScreenCaptureParameters.VideoCaptureParameters(); parameters.videoCaptureParameters.width = 1920; parameters.videoCaptureParameters.height = 1080; parameters.videoCaptureParameters.framerate = 30; parameters.videoCaptureParameters.bitrate = 4000; engine.updateScreenCaptureParameters(parameters); } // Handle screen sharing events private final IRtcEngineEventHandler eventHandler = new IRtcEngineEventHandler() { @Override // ... other event handlers ... }; // Placeholder for showToast method private void showToast(String message) { Toast.makeText(getContext(), message, Toast.LENGTH_SHORT).show(); } // Placeholder for TAG constant private static final String TAG = "ScreenSharingExample"; // Placeholder for Fragment and Bundle, assuming they are available in the context // import androidx.fragment.app.Fragment; // import android.os.Bundle; // import android.widget.Toast; // import android.util.Log; // import io.agora.rtc2.IRtcEngineEventHandler; // import io.agora.rtc2.ChannelMediaOptions; // import io.agora.rtc2.RtcEngine; } ``` -------------------------------- ### Android: Join Multiple Channels Simultaneously Source: https://context7.com/shengwang-community/api-examples/llms.txt Demonstrates joining two channels ('channel_1' and 'channel_2') with different UIDs and media publishing options. 'channel_1' publishes camera and microphone, while 'channel_2' is set to listen only. Includes methods for updating channel options, setting up remote video, and leaving channels. ```java // Android - JoinMultipleChannel.java import io.agora.rtc2.*; public class MultiChannelExample { private RtcEngineEx engine; private RtcConnection connection1; private RtcConnection connection2; private Map connections = new HashMap<>(); private void joinMultipleChannels() { // Create first connection connection1 = new RtcConnection(); connection1.channelId = "channel_1"; connection1.localUid = 1001; ChannelMediaOptions options1 = new ChannelMediaOptions(); options1.autoSubscribeAudio = true; options1.autoSubscribeVideo = true; options1.publishCameraTrack = true; // Publish camera to channel 1 options1.publishMicrophoneTrack = true; options1.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER; // Join first channel TokenUtils.gen(context, connection1.channelId, connection1.localUid, token1 -> { int result = engine.joinChannelEx( token1, connection1, options1, createEventHandler("channel_1") ); if (result == 0) { connections.put("channel_1", connection1); Log.i(TAG, "Joined channel_1"); } }); // Create second connection connection2 = new RtcConnection(); connection2.channelId = "channel_2"; connection2.localUid = 1002; // Different UID ChannelMediaOptions options2 = new ChannelMediaOptions(); options2.autoSubscribeAudio = true; options2.autoSubscribeVideo = true; options2.publishCameraTrack = false; // Don't publish to channel 2 options2.publishMicrophoneTrack = false; // Listen only options2.clientRoleType = Constants.CLIENT_ROLE_AUDIENCE; // Join second channel TokenUtils.gen(context, connection2.channelId, connection2.localUid, token2 -> { int result = engine.joinChannelEx( token2, connection2, options2, createEventHandler("channel_2") ); if (result == 0) { connections.put("channel_2", connection2); Log.i(TAG, "Joined channel_2"); } }); } private IRtcEngineEventHandler createEventHandler(String channelName) { return new IRtcEngineEventHandler() { @Override public void onJoinChannelSuccess(String channel, int uid, int elapsed) { Log.i(TAG, channelName + " joined: uid=" + uid); } @Override public void onUserJoined(int uid, int elapsed) { Log.i(TAG, channelName + " user joined: " + uid); // Setup video view for this channel } @Override public void onUserOffline(int uid, int reason) { Log.i(TAG, channelName + " user left: " + uid); } }; } private void updateChannelOptions(String channelName, boolean enablePublish) { RtcConnection connection = connections.get(channelName); if (connection == null) return; ChannelMediaOptions options = new ChannelMediaOptions(); options.publishCameraTrack = enablePublish; options.publishMicrophoneTrack = enablePublish; engine.updateChannelMediaOptionsEx(options, connection); Log.i(TAG, "Updated " + channelName + " publish: " + enablePublish); } private void setupRemoteVideoForChannel(String channelName, int uid, SurfaceView view) { RtcConnection connection = connections.get(channelName); if (connection == null) return; VideoCanvas canvas = new VideoCanvas(view, VideoCanvas.RENDER_MODE_HIDDEN, uid); engine.setupRemoteVideoEx(canvas, connection); } private void leaveChannel(String channelName) { RtcConnection connection = connections.get(channelName); if (connection == null) return; engine.leaveChannelEx(connection); connections.remove(channelName); Log.i(TAG, "Left " + channelName); } private void leaveAllChannels() { for (Map.Entry entry : connections.entrySet()) { engine.leaveChannelEx(entry.getValue()); } connections.clear(); } } ``` -------------------------------- ### Join Video Channel in iOS with Agora SDK Source: https://context7.com/shengwang-community/api-examples/llms.txt Swift implementation for joining an Agora video channel. Configures video encoding, audio routing, and handles channel lifecycle events. Requires AgoraRtcKit framework and proper AppId configuration. ```swift import AgoraRtcKit import UIKit class JoinChannelVideoViewController: UIViewController { var agoraKit: AgoraRtcEngineKit! var localView: UIView! var remoteView: UIView! var isJoined: Bool = false override func viewDidLoad() { super.viewDidLoad() // 1. Setup UI containers setupVideoViews() // 2. Initialize Agora engine let config = AgoraRtcEngineConfig() config.appId = KeyCenter.AppId config.channelProfile = .liveBroadcasting agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) // 3. Set broadcaster role agoraKit.setClientRole(.broadcaster) // 4. Enable video agoraKit.enableVideo() agoraKit.enableAudio() // 5. Configure video encoding agoraKit.setVideoEncoderConfiguration(AgoraVideoEncoderConfiguration( size: CGSize(width: 960, height: 540), frameRate: .fps15, bitrate: AgoraVideoBitrateStandard, orientationMode: .adaptative, mirrorMode: .auto )) // 6. Setup local video let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.uid = 0 videoCanvas.view = localView videoCanvas.renderMode = .hidden agoraKit.setupLocalVideo(videoCanvas) agoraKit.startPreview() // 7. Set audio route to speaker agoraKit.setDefaultAudioRouteToSpeakerphone(true) // 8. Join channel joinChannel(channelName: "test_channel") } func joinChannel(channelName: String) { let options = AgoraRtcChannelMediaOptions() options.publishCameraTrack = true options.publishMicrophoneTrack = true options.clientRoleType = .broadcaster options.autoSubscribeAudio = true options.autoSubscribeVideo = true NetworkManager.shared.generateToken(channelName: channelName, uid: 0) { [weak self] token in guard let self = self else { return } let result = self.agoraKit.joinChannel( byToken: token, channelId: channelName, uid: 0, mediaOptions: options ) if result != 0 { self.showAlert(title: "Error", message: "Join channel failed: \(result)") } } } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) agoraKit.disableAudio() agoraKit.disableVideo() if isJoined { agoraKit.stopPreview() agoraKit.leaveChannel { stats in print("Left channel, duration: \(stats.duration)s") } } } private func setupVideoViews() { localView = UIView() remoteView = UIView() view.addSubview(localView) view.addSubview(remoteView) // Add Auto Layout constraints... } } // MARK: - AgoraRtcEngineDelegate extension JoinChannelVideoViewController: AgoraRtcEngineDelegate { func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { isJoined = true print("Joined channel: \(channel), uid: \(uid)") } func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { print("Remote user joined: \(uid)") // Setup remote video let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.uid = uid videoCanvas.view = remoteView videoCanvas.renderMode = .hidden agoraKit.setupRemoteVideo(videoCanvas) } func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { print("Remote user left: \(uid), reason: \(reason.rawValue)") // Clear remote video let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.uid = uid videoCanvas.view = nil agoraKit.setupRemoteVideo(videoCanvas) } func rtcEngine(_ engine: AgoraRtcEngineKit, reportRtcStats stats: AgoraChannelStats) { print("Stats - users: \(stats.userCount), duration: \(stats.duration)s") } } ``` -------------------------------- ### Initialize Agora RTC Engine (Swift) Source: https://context7.com/shengwang-community/api-examples/llms.txt Initializes the Agora RTC engine in Swift for iOS and macOS. Requires the AgoraRtcKit framework. Configures app ID, channel profile, and optionally sets up a private access point and log file. The deinit method handles cleanup. ```swift import AgoraRtcKit class VideoCallViewController: UIViewController { var agoraKit: AgoraRtcEngineKit! var isJoined: Bool = false override func viewDidLoad() { super.viewDidLoad() // Create engine configuration let config = AgoraRtcEngineConfig() config.appId = "YOUR_APP_ID" // From Agora Console config.areaCode = .global // or .CN, .NA, .EU, .AS, .JP, .IN config.channelProfile = .liveBroadcasting // Initialize engine with delegate agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self) // Configure private cloud (optional) let privateConfig = AgoraLocalAccessPointConfiguration() privateConfig.ipList = ["10.0.0.1"] privateConfig.domainList = ["example.com"] agoraKit.setLocalAccessPoint(privateConfig) // Set log file path agoraKit.setLogFile("/path/to/logfile.log") } deinit { agoraKit.disableAudio() agoraKit.disableVideo() if isJoined { agoraKit.stopPreview() agoraKit.leaveChannel { stats in print("Left channel, duration: \(stats.duration)s") } } AgoraRtcEngineKit.destroy() } } // MARK: - AgoraRtcEngineDelegate extension VideoCallViewController: AgoraRtcEngineDelegate { func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinChannel channel: String, withUid uid: UInt, elapsed: Int) { isJoined = true print("Joined \(channel) with uid \(uid), elapsed: \(elapsed)ms") } func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { print("Remote user \(uid) joined") // Setup remote video canvas } func rtcEngine(_ engine: AgoraRtcEngineKit, didOfflineOfUid uid: UInt, reason: AgoraUserOfflineReason) { print("User \(uid) went offline: \(reason.rawValue)") // Remove remote video view } func rtcEngine(_ engine: AgoraRtcEngineKit, didOccurError errorCode: AgoraErrorCode) { print("SDK Error: \(errorCode.rawValue)") showAlert(title: "Error", message: "Error \(errorCode.rawValue) occurred") } } ``` -------------------------------- ### Initialize Agora RTC Engine (Android - Java) Source: https://context7.com/shengwang-community/api-examples/llms.txt This snippet demonstrates how to create and configure the Agora RTC engine instance on Android using Java. It involves setting up the application context, App ID, channel profile, audio scenario, and event handlers for callbacks like join success, user joining/leaving, and errors. It also shows optional private cloud configuration and engine cleanup. ```java import io.agora.rtc2.RtcEngine; import io.agora.rtc2.RtcEngineConfig; import io.agora.rtc2.IRtcEngineEventHandler; import io.agora.rtc2.Constants; // Create engine configuration RtcEngineConfig config = new RtcEngineConfig(); config.mContext = getApplicationContext(); config.mAppId = "YOUR_APP_ID"; // Get from Agora Console config.mChannelProfile = Constants.CHANNEL_PROFILE_LIVE_BROADCASTING; config.mAudioScenario = Constants.AudioScenario.getValue(Constants.AudioScenario.DEFAULT); config.mAreaCode = GlobalSettings.AREA_CODE_GLOB; // or specific regions // Set event handler for callbacks config.mEventHandler = new IRtcEngineEventHandler() { @Override public void onJoinChannelSuccess(String channel, int uid, int elapsed) { Log.i(TAG, "Joined channel: " + channel + " with uid: " + uid); runOnUiThread(() -> { // Update UI - user successfully joined }); } @Override public void onUserJoined(int uid, int elapsed) { Log.i(TAG, "Remote user joined: " + uid); // Setup remote video view for this user } @Override public void onUserOffline(int uid, int reason) { Log.i(TAG, "User " + uid + " left, reason: " + reason); // Remove remote user's video view } @Override public void onError(int err) { Log.e(TAG, "SDK Error: " + err + " - " + RtcEngine.getErrorDescription(err)); if (err == Constants.ERR_INVALID_TOKEN || err == Constants.ERR_TOKEN_EXPIRED) { // Handle token expiration engine.leaveChannel(); showAlert("Token expired. Please rejoin."); } } }; // Create the engine instance RtcEngine engine = RtcEngine.create(config); // Configure for private cloud (optional) LocalAccessPointConfiguration localAccessPoint = new LocalAccessPointConfiguration(); localAccessPoint.ipList = Arrays.asList("10.0.0.1"); localAccessPoint.domainList = Arrays.asList("example.com"); engine.setLocalAccessPoint(localAccessPoint); // Cleanup when done @Override protected void onDestroy() { super.onDestroy(); if (engine != null) { engine.leaveChannel(); } RtcEngine.destroy(); } ``` -------------------------------- ### Join Video Channel in Android using Java Source: https://context7.com/shengwang-community/api-examples/llms.txt This Java code snippet shows how to join a video channel using the Agora SDK on Android. It includes steps for setting up local and remote video views, configuring video encoding, and handling channel events. Dependencies include the Agora SDK, Android UI components, and potentially a utility for token generation. ```java // Android - JoinChannelVideo.java import io.agora.rtc2.*; import io.agora.rtc2.video.*; import android.view.SurfaceView; import android.widget.FrameLayout; public class JoinChannelVideo extends Fragment { private RtcEngine engine; private FrameLayout localContainer, remoteContainer; private boolean joined = false; private void joinChannel(String channelName) { // 1. Create and setup local video view SurfaceView localView = new SurfaceView(getContext()); localContainer.addView(localView, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT )); // 2. Setup local video canvas VideoCanvas localCanvas = new VideoCanvas(localView, VideoCanvas.RENDER_MODE_HIDDEN, 0); engine.setupLocalVideo(localCanvas); // 3. Set audio route to speaker engine.setDefaultAudioRoutetoSpeakerphone(true); // 4. Set client role as broadcaster engine.setClientRole(Constants.CLIENT_ROLE_BROADCASTER); // 5. Enable video module engine.enableVideo(); // 6. Configure video encoder engine.setVideoEncoderConfiguration(new VideoEncoderConfiguration( new VideoEncoderConfiguration.VideoDimensions(960, 540), // Resolution VideoEncoderConfiguration.FRAME_RATE.FRAME_RATE_FPS_15, // 15 fps VideoEncoderConfiguration.STANDARD_BITRATE, VideoEncoderConfiguration.ORIENTATION_MODE.ORIENTATION_MODE_ADAPTIVE )); // 7. Setup channel media options ChannelMediaOptions options = new ChannelMediaOptions(); options.autoSubscribeAudio = true; options.autoSubscribeVideo = true; options.publishMicrophoneTrack = true; options.publishCameraTrack = true; options.clientRoleType = Constants.CLIENT_ROLE_BROADCASTER; // 8. Generate token and join channel int uid = new Random().nextInt(1000) + 100000; TokenUtils.gen(requireContext(), channelName, uid, token -> { int result = engine.joinChannel(token, channelName, uid, options); if (result != 0) { showAlert("Join failed: " + RtcEngine.getErrorDescription(Math.abs(result))); } }); } private final IRtcEngineEventHandler eventHandler = new IRtcEngineEventHandler() { @Override public void onJoinChannelSuccess(String channel, int uid, int elapsed) { joined = true; Log.i(TAG, "Joined channel: " + channel + ", uid: " + uid); } @Override public void onUserJoined(int uid, int elapsed) { runOnUiThread(() -> { // Create remote video view SurfaceView remoteView = new SurfaceView(getContext()); remoteView.setZOrderMediaOverlay(true); remoteContainer.addView(remoteView, new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT )); // Setup remote video canvas VideoCanvas remoteCanvas = new VideoCanvas(remoteView, VideoCanvas.RENDER_MODE_HIDDEN, uid); engine.setupRemoteVideo(remoteCanvas); }); } @Override public void onUserOffline(int uid, int reason) { runOnUiThread(() -> { // Remove remote video view remoteContainer.removeAllViews(); engine.setupRemoteVideo(new VideoCanvas(null, VideoCanvas.RENDER_MODE_HIDDEN, uid)); }); } @Override public void onRemoteVideoStateChanged(int uid, int state, int reason, int elapsed) { Log.i(TAG, "Remote video state changed: uid=" + uid + ", state=" + state + ", reason=" + reason); } }; private void leaveChannel() { if (joined) { engine.leaveChannel(); joined = false; localContainer.removeAllViews(); remoteContainer.removeAllViews(); } } } ``` -------------------------------- ### CMake Configuration for Native Android Library Source: https://github.com/shengwang-community/api-examples/blob/main/Android/APIExample/agora-simple-filter/src/main/cpp/CMakeLists.txt This CMake script configures the build for a native Android library. It sets the minimum CMake version, defines the project name, links the Agora and OpenCV shared libraries, includes necessary header directories, and specifies C++ compiler flags and target libraries for the native build. ```cmake cmake_minimum_required(VERSION 3.4.1) project(agora-simple-filter) #link agora so set(agora-lib-so ${PROJECT_SOURCE_DIR}/../agoraLibs/${CMAKE_ANDROID_ARCH_ABI}/libagora-rtc-sdk.so) link_libraries(${agora-lib-so}) #link opencv so set(opencv-lib-so ${PROJECT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libopencv_java4.so) link_libraries(${opencv-lib-so}) #opencv inc set(opencv-inc ${PROJECT_SOURCE_DIR}/../cpp/plugin_source_code) include_directories(${opencv-inc}) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. agora-simple-filter # Sets the library as a shared library. SHARED plugin_source_code/ExtensionProvider.cpp plugin_source_code/ExtensionVideoFilter.cpp plugin_source_code/ExtensionAudioFilter.cpp plugin_source_code/EGLCore.cpp plugin_source_code/JniHelper.cpp plugin_source_code/VideoProcessor.cpp plugin_source_code/AudioProcessor.cpp plugin_source_code/external_thread_pool.cpp # Provides a relative path to your source file(s). agora-filter.cpp) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_include_directories(agora-simple-filter PRIVATE ${PROJECT_SOURCE_DIR}) target_include_directories(agora-simple-filter PRIVATE ${PROJECT_SOURCE_DIR}/AgoraRtcKit) target_link_libraries( # Specifies the target library. agora-simple-filter ${agora-lib-so} ${agora-ffmpeg-so} ${agora-soundtouch-so} ${agora-fdkaac-so} ${opencv-lib-so} # Links the target library to the log library # included in the NDK. ${log-lib} # ${GLESv2} ${GLESv3} EGL android) ``` -------------------------------- ### Apply Voice Effects and Spatial Audio (iOS/Swift) Source: https://context7.com/shengwang-community/api-examples/llms.txt Shows how to implement voice changing effects and 3D spatial audio positioning in an iOS app using Agora RTC. Covers setting audio profile/preset, applying beautifier/changer/transformations, customizing pitch/equalizer/reverb, enabling spatial audio and updating positions, and playing/stopping local audio effects with callbacks. ```Swift // iOS - VoiceEffects.swift import AgoraRtcKit class VoiceEffectsViewController: UIViewController { var agoraKit: AgoraRtcEngineKit! func setupAudioEffects() { // 1. Set audio profile for high quality agoraKit.setAudioProfile(.musicHighQualityStereo) agoraKit.setAudioScenario(.gameStreaming) // or .chatRoom, .chorus // 2. Apply preset voice effects applyVoiceBeautifier() } func applyVoiceBeautifier() { // Voice beautifier presets agoraKit.setVoiceBeautifierPreset(.presetChatBeautifierMagnetic) // Options: .presetChatBeautifierFresh, .presetChatBeautifierVitality, // .presetSingingBeautifier, .presetTimbreTransformationVigorous, etc. } func applyVoiceChanger() { // Voice changer presets agoraKit.setAudioEffectPreset(.voiceChangerEffectHulk) // Options: .voiceChangerEffectBoy, .voiceChangerEffectGirl, // .voiceChangerEffectPigKing, .voiceChangerEffectOldMan, etc. } func applyStyleTransformation() { // Style transformation presets agoraKit.setAudioEffectPreset(.styleTransformationPopular) // Options: .styleTransformationRnB, .styleTransformationHipHop, etc. } func applyCustomVoiceEffect() { // Custom voice parameters agoraKit.setLocalVoicePitch(1.5) // 1.0 = normal, 0.5-2.0 range agoraKit.setLocalVoiceEqualization(.band31, gain: -15) // -15dB to 15dB agoraKit.setLocalVoiceReverb(.dryLevel, value: -1) agoraKit.setLocalVoiceReverb(.wetLevel, value: -7) agoraKit.setLocalVoiceReverb(.roomSize, value: 57) agoraKit.setLocalVoiceReverb(.wetDelay, value: 135) agoraKit.setLocalVoiceReverb(.strength, value: 45) } func applyRoomAcoustics() { // Room acoustics presets agoraKit.setAudioEffectPreset(.roomAcousticsKTV) // Options: .roomAcousticsVocalConcert, .roomAcousticsStudio, // .roomAcousticsPhonograph, .roomAcousticsVirtualStereo, etc. } func setupSpatialAudio() { // 1. Enable spatial audio let spatialAudioParams = AgoraSpatialAudioParams() spatialAudioParams.enable_blur = true spatialAudioParams.enable_air_absorb = true agoraKit.enableSpatialAudio(true) // 2. Set audio reception range agoraKit.setAudioRecvRange(50) // Range in game units // 3. Update local user position (for spatial audio) updateLocalPosition(x: 0, y: 0, z: 0, forward: [1, 0, 0]) } func updateLocalPosition(x: Float, y: Float, z: Float, forward: [Float]) { let position: [NSNumber] = [NSNumber(value: x), NSNumber(value: y), NSNumber(value: z)] let axisForward: [NSNumber] = forward.map { NSNumber(value: $0) } let axisRight: [NSNumber] = [1, 0, 0] let axisUp: [NSNumber] = [0, 1, 0] agoraKit.updateSelfPosition( position, axisForward: axisForward, axisRight: axisRight, axisUp: axisUp ) } func updateRemoteUserPosition(uid: UInt, x: Float, y: Float, z: Float) { let position: [NSNumber] = [NSNumber(value: x), NSNumber(value: y), NSNumber(value: z)] let forward: [NSNumber] = [1, 0, 0] agoraKit.updateRemotePosition( uid, positionInfo: position, forward: forward ) } func playAudioEffect() { // Play local audio effect file let effectId: Int32 = 1 let filePath = Bundle.main.path(forResource: "applause", ofType: "mp3")! agoraKit.playEffect( effectId, filePath: filePath, loopCount: 0, // 0 = play once, -1 = loop forever pitch: 1.0, pan: 0.0, // -1.0 (left) to 1.0 (right) gain: 100.0, // Volume 0-100 publish: true, // Publish to remote users startPos: 0 // Start position in ms ) } func stopAudioEffect(effectId: Int32) { agoraKit.stopEffect(effectId) } func adjustEffectVolume(effectId: Int32, volume: Int) { agoraKit.setVolumeOfEffect(effectId, volume: Int32(volume)) // 0-100 } func clearAllEffects() { // Clear all audio effects agoraKit.setAudioEffectPreset(.audioEffectOff) agoraKit.setVoiceBeautifierPreset(.voiceBeautifierOff) agoraKit.setLocalVoicePitch(1.0) } } // MARK: - Delegate callbacks extension VoiceEffectsViewController: AgoraRtcEngineDelegate { func rtcEngine(_ engine: AgoraRtcEngineKit, audioEffectFinished soundId: Int32) { print("Audio effect \(soundId) finished playing") } } ```