### Start Publishing Audio Stream Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Publish a local audio stream to the room. Configure audio settings like bitrate, channel, and codec. Enable echo cancellation, noise suppression, and automatic gain control for better audio quality. Each stream is identified by a unique streamID. ```swift func startPublishing(streamID: String) { // Configure audio settings before publishing let audioConfig = ZegoAudioConfig() audioConfig.bitrate = 48 // Audio bitrate in kbps audioConfig.channel = .mono // Mono or stereo audioConfig.codecID = .default // Audio codec ZegoExpressEngine.shared().setAudioConfig(audioConfig) // Enable echo cancellation and noise suppression ZegoExpressEngine.shared().enableAEC(true) ZegoExpressEngine.shared().enableANS(true) ZegoExpressEngine.shared().enableAGC(true) // Start publishing the audio stream ZegoExpressEngine.shared().startPublishingStream(streamID) print("Started publishing stream: \(streamID)") } func stopPublishing() { ZegoExpressEngine.shared().stopPublishingStream() print("Stopped publishing stream") } ``` -------------------------------- ### Initialize ZegoExpressEngine Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Initialize the ZegoExpressEngine singleton instance with your application ID and sign. This step is mandatory before using any other SDK features. Ensure you replace placeholder credentials with your actual ZEGO Admin Console values. ```swift import ZegoExpressEngine class AudioManager { func initializeEngine() { // Get your appID and appSign from ZEGO Admin Console let appID: UInt32 = 123456789 let appSign = "your_app_sign_here" // Create engine profile let profile = ZegoEngineProfile() profile.appID = appID profile.appSign = appSign profile.scenario = .broadcast // Use .communication for voice calls // Initialize the engine ZegoExpressEngine.createEngine(with: profile, eventHandler: self) print("ZegoExpressEngine initialized successfully") } } extension AudioManager: ZegoEventHandler { func onRoomStateChanged(_ state: ZegoRoomState, errorCode: Int32, extendedData: [AnyHashable : Any], roomID: String) { print("Room state changed: \(state), errorCode: \(errorCode)") } } ``` -------------------------------- ### Integrate Zego Express Audio in iOS Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt A complete implementation of a view controller managing engine initialization, room login, and audio stream lifecycle. ```swift import UIKit import ZegoExpressEngine class VoiceChatViewController: UIViewController { private let appID: UInt32 = 123456789 private let appSign = "your_app_sign_here" private let roomID = "voice_room_001" private let userID = "user_123" private let streamID = "stream_user_123" override func viewDidLoad() { super.viewDidLoad() initializeZego() } private func initializeZego() { let profile = ZegoEngineProfile() profile.appID = appID profile.appSign = appSign profile.scenario = .communication ZegoExpressEngine.createEngine(with: profile, eventHandler: self) joinRoom() } private func joinRoom() { let user = ZegoUser(userID: userID, userName: "User 123") let config = ZegoRoomConfig() config.isUserStatusNotify = true ZegoExpressEngine.shared().loginRoom(roomID, user: user, config: config) { [weak self] errorCode, _ in guard errorCode == 0 else { print("Join room failed: \(errorCode)") return } self?.startPublishing() } } private func startPublishing() { ZegoExpressEngine.shared().enableAEC(true) ZegoExpressEngine.shared().enableANS(true) ZegoExpressEngine.shared().startPublishingStream(streamID) } deinit { ZegoExpressEngine.shared().stopPublishingStream() ZegoExpressEngine.shared().logoutRoom(roomID) ZegoExpressEngine.destroy(nil) } } extension VoiceChatViewController: ZegoEventHandler { func onRoomStateChanged(_ state: ZegoRoomState, errorCode: Int32, extendedData: [AnyHashable : Any], roomID: String) { switch state { case .connected: print("Connected to room") case .connecting: print("Connecting to room...") case .disconnected: print("Disconnected from room") @unknown default: break } } func onRoomStreamUpdate(_ updateType: ZegoUpdateType, streamList: [ZegoStream], extendedData: [AnyHashable : Any]?, roomID: String) { for stream in streamList { if updateType == .add { ZegoExpressEngine.shared().startPlayingStream(stream.streamID) } else { ZegoExpressEngine.shared().stopPlayingStream(stream.streamID) } } } func onPublisherStateUpdate(_ state: ZegoPublisherState, errorCode: Int32, extendedData: [AnyHashable : Any]?, streamID: String) { print("Publisher state: \(state), error: \(errorCode)") } func onPlayerStateUpdate(_ state: ZegoPlayerState, errorCode: Int32, extendedData: [AnyHashable : Any]?, streamID: String) { print("Player state: \(state), error: \(errorCode)") } } ``` -------------------------------- ### Add Swift Package Dependency Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Add the Zego Express Audio SDK to your project using Swift Package Manager. Specify the repository URL and version in your Package.swift file or through Xcode's package management interface. ```swift // In your Package.swift dependencies: dependencies: [ .package(url: "https://github.com/zegolibrary/express-audio-ios.git", from: "3.23.1") ] // Or add via Xcode: // File > Add Packages > Enter repository URL: // https://github.com/zegolibrary/express-audio-ios.git ``` -------------------------------- ### Login to a Room Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Join a room to enable communication between users. Configure room settings such as user status notifications and maximum member count. The room acts as a channel for audio streams. ```swift func loginRoom(roomID: String, userID: String, userName: String) { // Create user object let user = ZegoUser(userID: userID, userName: userName) // Configure room settings let roomConfig = ZegoRoomConfig() roomConfig.isUserStatusNotify = true // Receive notifications when users join/leave roomConfig.maxMemberCount = 0 // 0 means unlimited // Login to the room ZegoExpressEngine.shared().loginRoom(roomID, user: user, config: roomConfig) { errorCode, extendedData in if errorCode == 0 { print("Successfully joined room: \(roomID)") } else { print("Failed to join room, error code: \(errorCode)") } } } ``` -------------------------------- ### Play and Stop Remote Audio Streams Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Functions to initiate and terminate remote stream playback, including a delegate-style handler for room stream updates. ```swift func startPlaying(streamID: String) { // Start playing the remote audio stream ZegoExpressEngine.shared().startPlayingStream(streamID) print("Started playing stream: \(streamID)") } func stopPlaying(streamID: String) { ZegoExpressEngine.shared().stopPlayingStream(streamID) print("Stopped playing stream: \(streamID)") } // Handle stream updates in the room extension AudioManager { func onRoomStreamUpdate(_ updateType: ZegoUpdateType, streamList: [ZegoStream], extendedData: [AnyHashable : Any]?, roomID: String) { for stream in streamList { if updateType == .add { // New stream available, start playing startPlaying(streamID: stream.streamID) } else { // Stream removed, stop playing stopPlaying(streamID: stream.streamID) } } } } ``` -------------------------------- ### Logout Room and Destroy Engine Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Procedures for exiting a room and releasing engine resources to prevent memory leaks. ```swift func logoutRoom(roomID: String) { ZegoExpressEngine.shared().logoutRoom(roomID) { errorCode, extendedData in if errorCode == 0 { print("Successfully left room: \(roomID)") } else { print("Failed to leave room, error code: \(errorCode)") } } } func destroyEngine() { ZegoExpressEngine.destroy { print("ZegoExpressEngine destroyed successfully") } } ``` -------------------------------- ### Control Local and Remote Audio Muting Source: https://context7.com/zegolibrary/express-audio-ios/llms.txt Methods to toggle microphone input, publishing status, remote stream playback, and audio routing. ```swift func muteLocalMicrophone(_ mute: Bool) { // Mute/unmute the local microphone (still sends silent audio) ZegoExpressEngine.shared().muteMicrophone(mute) print("Microphone muted: \(mute)") } func muteLocalPublishing(_ mute: Bool) { // Mute/unmute publishing (stops sending audio data entirely) ZegoExpressEngine.shared().mutePublishStreamAudio(mute) print("Publishing muted: \(mute)") } func muteRemoteStream(_ streamID: String, mute: Bool) { // Mute/unmute a specific remote stream ZegoExpressEngine.shared().mutePlayStreamAudio(streamID, mute: mute) print("Stream \(streamID) muted: \(mute)") } func setSpeakerOutput(_ useSpeaker: Bool) { // Route audio to speaker or earpiece ZegoExpressEngine.shared().setAudioRouteToSpeaker(useSpeaker) print("Audio route to speaker: \(useSpeaker)") } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.