Skip to content

Latest commit

 

History

History
143 lines (118 loc) · 10.3 KB

ARCHITECTURE.md

File metadata and controls

143 lines (118 loc) · 10.3 KB

macOS ARCHITECTURE

macOS example project using Swift + Cocoa. Demonstrates Agora RTC SDK features through a collection of self-contained examples organized by complexity.

Technology Stack

  • Language: Swift
  • UI Framework: Cocoa (AppKit)
  • Architecture: Single-window application with example selection
  • State: Instance variables + delegate callbacks

Directory Structure

macOS/
├── APIExample/
│   ├── Examples/
│   │   ├── Basic/
│   │   │   └── <ExampleName>/
│   │   │       ├── <ExampleName>.swift
│   │   │       └── SKILL.md          # Per-example agent guide (present or forthcoming)
│   │   └── Advanced/
│   │       └── <ExampleName>/
│   │           ├── <ExampleName>.swift
│   │           └── SKILL.md          # Per-example agent guide (present or forthcoming)
│   ├── Common/              # Shared utilities (KeyCenter, GlobalSettings, LogUtils, Util)
│   ├── Resources/
│   ├── Base.lproj/          # Base storyboards
│   ├── zh-Hans.lproj/       # Simplified Chinese project localization
│   ├── AppDelegate.swift
│   └── ViewController.swift # Main window controller
├── SimpleFilter/            # Specialized filter example
├── APIExample.xcodeproj/    # Xcode project
├── APIExample.xcworkspace/  # Xcode workspace
├── libs/                    # SDK libraries
├── Pods/                    # CocoaPods dependencies
├── .agents/skills/query-cases/  # Read-only case and registration discovery
├── .agents/skills/upsert-case/  # Add or modify a case
├── .agents/skills/review-case/  # Review lifecycle, threading, and conventions
├── AGENTS.md                # Agent guide
└── ARCHITECTURE.md          # This file

Architectural Rules

Example Structure

Each example lives in its own folder under APIExample/Examples/Basic/ or APIExample/Examples/Advanced/ and consists of:

  • A Swift file containing the example implementation
  • A per-example storyboard, typically at Base.lproj/<ExampleName>.storyboard

Example Pattern

Each example is a self-contained class that:

  • Manages its own Agora engine lifecycle
  • Implements AgoraRtcEngineDelegate
  • Receives configuration via initialization or property injection
  • Owns all UI elements for that example

Menu Registration

All examples are registered in APIExample/ViewController.swift via a menu or list structure. The example name must match the folder name.

Naming

  • Example folder names: PascalCase (e.g., JoinChannelVideo)
  • Example class: <ExampleName> (e.g., JoinChannelVideo)

Common Utilities

All examples share utilities from APIExample/Common/:

  • KeyCenter — App ID and optional Certificate
  • GlobalSettings — Shared runtime configuration
  • LogUtils — SDK log path
  • Util — Privatization configuration

Case Index

Case Path Key APIs Description
JoinChannelAudio Examples/Basic/JoinChannelAudio/ createAgoraRtcEngine(), setAudioScenario(), joinChannel(), leaveChannel(), destroy() Basic audio call — select an audio scenario, join a channel, and manage the audio stream
JoinChannelVideo Examples/Basic/JoinChannelVideo/ createAgoraRtcEngine(), joinChannel(), setupLocalVideo(), setupRemoteVideo(), leaveChannel(), destroy() Basic video call — join channel and render local/remote video
JoinChannelVideo(Token) Examples/Basic/JoinChannelVideo(Token)/ createAgoraRtcEngine(), joinChannel() with token, setupLocalVideo(), setupRemoteVideo() Video call with token authentication
JoinChannelVideo(Recorder) Examples/Basic/JoinChannelVideo(Recorder)/ createAgoraRtcEngine(), joinChannel(), startAudioRecording(), stopAudioRecording() Video call with local audio recording
AgoraBeauty Examples/Advanced/AgoraBeauty/ createVideoEffectObject(), setVideoEffectStringParam(), enableVirtualBackground() Beauty filter and enhancement effects
AudioMixing Examples/Advanced/AudioMixing/ setAudioScenario(), startAudioMixing(), stopAudioMixing(), pauseAudioMixing(), resumeAudioMixing() Audio scenario selection, file mixing, and playback control
ChannelMediaRelay Examples/Advanced/ChannelMediaRelay/ startChannelMediaRelay(), updateChannelMediaRelay(), stopChannelMediaRelay() Relay media streams across multiple channels
ContentInspect Examples/Advanced/ContentInspect/ enableContentInspect(), disableContentInspect() Content inspection and moderation
CreateDataStream Examples/Advanced/CreateDataStream/ createDataStream(), sendStreamMessage() Custom data stream creation and messaging
CustomAudioRender Examples/Advanced/CustomAudioRender/ setExternalAudioSink(), pullAudioFrame() Custom audio rendering pipeline
CustomAudioSource Examples/Advanced/CustomAudioSource/ setExternalAudioSource(), pushAudioFrame() Custom audio source capture
CustomVideoRender Examples/Advanced/CustomVideoRender/ setExternalVideoSink(), pullVideoFrame() Custom video rendering pipeline
CustomVideoSourceMediaIO Examples/Advanced/CustomVideoSourceMediaIO/ setExternalVideoSource(), pushVideoFrame() with MediaIO Custom video source with media I/O
CustomVideoSourcePush Examples/Advanced/CustomVideoSourcePush/ setExternalVideoSource(), pushVideoFrame() Custom video source push
CustomVideoSourcePushMulti Examples/Advanced/CustomVideoSourcePushMulti/ setExternalVideoSource(), pushVideoFrame() with multiple sources Multiple custom video sources
JoinMultiChannel Examples/Advanced/JoinMultiChannel/ createRtcChannel(), joinChannel() on multiple channels Join and manage multiple channels simultaneously
LiveStreaming Examples/Advanced/LiveStreaming/ setClientRole(), addVideoWatermark() with WatermarkConfig, startRtmpStreamWithTranscoding(), stopRtmpStream() Live streaming with watermark configuration and RTMP transcoding
LocalVideoTranscoding Examples/Advanced/LocalVideoTranscoding/ getScreenCaptureSources(), startLocalVideoTranscoder(), updateLocalTranscoderConfiguration(), stopLocalVideoTranscoder() Local video transcoding and composition
MediaPlayer Examples/Advanced/MediaPlayer/ createMediaPlayer(), open(), play(), pause(), stop() Media file playback and control
MultiCameraSourece Examples/Advanced/MultiCameraSourece/ enumerateDevices(), setDevice() with multiple cameras Multiple camera source selection
Multipath Examples/Advanced/Multipath/ enableMultipath(), setMultipathConfig() Multipath redundancy for reliability
PrecallTest Examples/Advanced/PrecallTest/ startEchoTest(), stopEchoTest(), startNetworkTest(), stopNetworkTest() Pre-call network and device testing
QuickSwitchChannel Examples/Advanced/QuickSwitchChannel/ switchChannel() Quick channel switching without reconnection
RawAudioData Examples/Advanced/RawAudioData/ setAudioFrameDelegate(), onMixedAudioFrame() Raw audio frame access and processing
RawMediaData Examples/Advanced/RawMediaData/ setVideoFrameDelegate(), setAudioFrameDelegate() Raw audio and video frame access
RawVideoData Examples/Advanced/RawVideoData/ setVideoFrameDelegate(), onCapturedVideoFrame(), onRemoteVideoFrame() Raw video frame capture and processing
RtePlayer Examples/Advanced/RtePlayer/ createMediaPlayer(), open() with RTE protocol RTE protocol media playback
RTMPStreaming Examples/Advanced/RTMPStreaming/ startRtmpStreamWithTranscoding(), updateRtmpTranscodingConfig(), stopRtmpStream() RTMP streaming with live transcoding
ScreenShare Examples/Advanced/ScreenShare/ startScreenCapture(), updateScreenCaptureParameters(), stopScreenCapture() Screen sharing and capture
SimpleFilter Examples/Advanced/SimpleFilter/ enableExtension(), setExtensionPropertyWithVendor(), onEventWithContext() Simple audio and video filter extensions with context-aware event callbacks
Simulcast Examples/Advanced/Simulcast/ setSimulcastConfig(), enableSimulcast() Simulcast streaming with multiple bitrates
SpatialAudio Examples/Advanced/SpatialAudio/ getLocalSpatialAudioEngine(), updateSelfPosition(), updateRemotePosition() 3D spatial audio positioning
StreamEncryption Examples/Advanced/StreamEncryption/ enableEncryption(), setEncryptionConfig() Stream encryption and security
VideoProcess Examples/Advanced/VideoProcess/ setVideoEncoderConfiguration(), setBeautyEffectOptions() Video processing and enhancement
VoiceChanger Examples/Advanced/VoiceChanger/ setVoiceBeautifierPreset(), setAudioEffectPreset() Voice effects and voice changer

Engine Lifecycle

The main case controller creates its engine using AgoraRtcEngineKit.sharedEngine(with:delegate:) and AgoraRtcEngineConfig. After media configuration and permission checks, it joins with joinChannel(byToken:channelId:uid:mediaOptions:).

The host calls viewWillBeRemovedFromSplitView() when switching cases. Cleanup invalidates pending Token/join requests, stops case-owned media, calls leaveChannel(nil) and AgoraRtcEngineKit.destroy(), then clears the engine reference. SDK delegate callbacks may arrive on background threads; AppKit updates go to the main queue.

See upsert-case and review-case for implementation and verification steps.

Token Flow

KeyCenter supplies AppId and optional Certificate. The basic case uses NetworkManager.shared.generateToken(channelName:uid:success:) to obtain a Token for the same channel and UID passed to joinChannel(byToken:channelId:uid:mediaOptions:). A case may also expose explicit Token input. There is no KeyCenter.Token API.

When Certificate is absent, the helper returns nil for projects that do not require Token authentication. When authentication is required, handle a failed request explicitly, and refresh expiring tokens using renewToken(_:). Before using an asynchronous response, confirm the request still belongs to the active case and engine. Production tokens should be generated on a server.