Professional live streaming from your iPhone, powered by Nostr and Bitcoin.
What is Swae? • Features • Getting Started • Architecture • Contributing • Roadmap
Swae is the only professional-grade IRL streaming app on iOS built natively on the Nostr protocol. It turns your iPhone into a complete broadcast studio — GPU-accelerated video effects, on-stream chat overlays, hardware integrations, scene management, and real-time Lightning payments — all in a single free app.
No desktop. No capture card. No OBS. No expensive equipment. Just your iPhone.
Why Nostr? Your identity is your keypair, portable across every Nostr client. Your audience follows you across relays, not locked to a single server. Your income arrives as Lightning zaps — settled instantly, no platform cut, no minimum payouts, no bank account required, and no one can freeze or censor your earnings.
Why Bitcoin? Streamers are among the most frequently deplatformed creators on the internet. Platforms like Twitch, YouTube, and TikTok wipe out channels, audiences, and income overnight. Swae gives creators financial sovereignty: instant, borderless payments that no centralized processor can withhold.
📖 For a deep dive into the codebase, see the Architecture Guide and Video Pipeline Guide.
- RTMP, SRT, and HLS protocol support
- Adaptive bitrate — real-time adjustment for unstable cellular networks
- SRTLA (SRT Link Aggregation) — bonds WiFi + cellular for redundant delivery
- Multi-destination RTMP — stream to Nostr and Twitch/Kick/YouTube simultaneously
- Background streaming — keep broadcasting when the app is backgrounded
- Landscape and portrait orientation support
- Configurable metadata — title, description, cover image, tags, content warnings, categories
- Real-time stats — uptime, bitrate, FPS, viewer count
Over 30 GPU-accelerated video effects composited directly into the broadcast output:
| Effect | Description |
|---|---|
| Chat Overlay | Renders live Nostr chat on-stream with full visual customization |
| Zap Plasma | Custom Metal shader — plasma tendrils converge on the stream when zaps arrive |
| Guest PiP | WebRTC remote video composited as picture-in-picture |
| Browser Widget | Embed any web content (alerts, overlays, dashboards) |
| Beauty / Face | Real-time face detection and beauty filters |
| LUT | Color grading with lookup tables |
| Text / Image / Shape | Custom overlays with positioning |
| Map | Live location map overlay |
| QR Code | Dynamic QR code generation on-stream |
| Remove Background | AI-powered background removal |
| VTuber | Virtual avatar driven by face tracking |
| Draw on Stream | Freehand drawing directly on the video |
| Poll | Interactive polls rendered into the broadcast |
| Replay | Instant replay effect |
| Twin / Triple | Multi-camera split effects |
| Pixellate / Pinch / Whirlpool | Distortion effects |
| Grayscale / Sepia / Opacity | Color manipulation |
| Slideshow / Movie | Media playback overlays |
| 360° Dewarp | Spherical video correction |
| Scoreboard | Sports scoreboard overlay |
All effects run on the GPU via Core Image and MetalPetal — no frame drops, even with multiple widgets active.
Scene Management — configure different widget layouts and switch between them live, just like OBS scenes.
- Send and receive zaps during live streams
- Built-in Lightning wallet with NWC (Nostr Wallet Connect) support
- One-click Coinos wallet creation from your Nostr identity
- Auto-topup — automatically fund streaming costs from your wallet
- Invoice generation and payment with QR codes
- Balance tracking with runway estimation
- Transaction history and zap receipt tracking
- Zap feed — real-time activity of incoming zaps
- Invite a guest onto your stream with a single tap
- Picture-in-picture video composited directly into the broadcast
- Mixed audio — guest audio mixed into the RTMP output
- Signaled over Nostr — NIP-04 encrypted DMs, no centralized server
- Heartbeat monitoring — automatic detection of connection loss
- ICE restart — graceful recovery from network changes
| Device | Capability |
|---|---|
| GoPro | Use as stream source via WiFi |
| DJI Drones | Stream aerial footage directly |
| External Display | Monitor your stream on a second screen |
- Hero section — featured live streams with parallax scrolling
- Category browsing — IRL, Gaming, Music, Talk, Art, Gambling, Sports, Cooking, Education, Tech, and more
- Search — find streams and users with Trie-based instant search + Profilestr API
- Most Zapped Streamers — rankings by Lightning tips
- Following feed — streams from people you follow
- Twitter/X-style profiles — banner, profile pic, bio, follow/unfollow, zap button
- QR code sharing — share your Nostr profile via QR
- View live chat on your wrist
- Stream monitoring and controls
- Chat preview with emote support
- Control panel with live chat and quick actions
- OBS WebSocket remote control support
- Stream key management for scheduled and recurring streams
- Ingest server — run a local RTMP/SRT/RIST ingest
- Private keys stored in the iOS Keychain with hardware-backed encryption
- Face ID / Touch ID required to view or copy keys
- Sensitive data automatically cleared from clipboard
- No key material ever logged
- Xcode 15.0+ (latest recommended)
- iOS 17.0+ deployment target
- Swift 5.9+
- An Apple Developer account (for device testing)
# Clone the repository
git clone https://github.com/suhailsaqan/swae.git
cd swae
# Open in Xcode
open swae.xcodeproj- Xcode will automatically resolve Swift Package Manager dependencies
- Select your target device or simulator
- Build and run (⌘R)
Coinos API Key (optional, for wallet creation):
- Copy
swae/Services/CoinosApiKey.exampletoswae/Services/CoinosApiKey.swift - Add your Coinos API key
- Create an account — generate a new Nostr keypair, or sign in with an existing one
- Connect a wallet — link a Lightning wallet via NWC or create one with Coinos
- Go live — tap the camera tab, configure your stream, and hit the Go Live orb
📖 Full details in docs/ARCHITECTURE.md
swae/
├── swaeApp.swift # App entry point (UIApplicationDelegate + SceneDelegate)
├── AppCoordinator.swift # Singleton — initializes SwiftData, AppState, Model
├── RootViewController.swift # UIKit root hosting SwiftUI content
├── ContentView.swift # SwiftUI content view
│
├── Controllers/ # UIKit view controllers
│ ├── AppState.swift # Global Nostr protocol state (relays, events, wallet)
│ ├── ModernTabBarController.swift # iOS 18+ tab bar with Liquid Glass
│ ├── ProfileViewController.swift # Twitter/X-style profile
│ ├── Camera/ # Camera & streaming UI
│ ├── ControlPanel/ # Streamer dashboard
│ ├── Onboarding/ # Sign up / sign in flow
│ └── Profile/ # Edit profile, following list
│
├── Various/Model/ # Core streaming model
│ ├── Model.swift # Stream config, effects, camera, widgets
│ ├── ModelNostrChat.swift # Chat bridge (AppState → NostrChatEffect)
│ ├── ModelCollab.swift # WebRTC collaboration state
│ └── ModelGoProDevice.swift # GoPro device state
│
├── Models/ # Data models & view models
│ ├── NostrEventStore.swift # Centralized NIP-16/33/53 deduplication
│ ├── WalletModel.swift # NWC wallet state
│ ├── CollabCallState.swift # WebRTC call lifecycle
│ ├── SearchViewModel.swift # Search with Trie + Profilestr
│ ├── StreamCategory.swift # Category definitions
│ └── ...
│
├── Services/ # Business logic services
│ ├── WebRTCService.swift # WebRTC peer connection management
│ ├── NWCClient.swift # Actor-based Nostr Wallet Connect
│ ├── AudioMixerService.swift # Audio mixing for collab
│ ├── ZapService.swift # Lightning zap operations
│ ├── LNURLService.swift # LNURL protocol
│ ├── CoinosClient.swift # Coinos API integration
│ └── ...
│
├── VideoEffects/ # 30+ GPU-accelerated effects
│ ├── NostrChatEffect.swift # Chat overlay rendering
│ ├── ZapPlasmaEffect.swift # Metal shader zap visualization
│ ├── GuestVideoCompositor.swift # WebRTC PiP compositing
│ └── ...
│
├── Metal/ # Custom Metal shaders
│ ├── ZapPlasmaShaders.metal # Plasma tendril animation
│ ├── BubblyOrbShaders.metal # Animated orb button
│ ├── ParticleCompute.metal # GPU particle simulation
│ └── ...
│
├── Components/ # Reusable UI components
│ ├── LiquidGlass/ # iOS 26-style morphing glass modals
│ ├── StreamCard/ # Stream card cells
│ ├── ZapButton.swift # Zap interaction button
│ └── ...
│
├── Views/ # SwiftUI + UIKit views
│ ├── VideoListViewController.swift # Home feed with hero + carousels
│ ├── StreamCamera/ # Camera, settings, stream views
│ ├── Wallet/ # Wallet UI (balance, send, receive)
│ ├── Onboarding/ # Onboarding flow
│ └── ...
│
├── Integrations/ # External hardware & services
│ ├── GoPro/ # Bluetooth + WiFi GoPro control
│ ├── Dji/ # DJI drone integration
│ ├── Tesla/ # Tesla vehicle integration
│ ├── ZapStreamCore/ # zap.stream API client
│ └── ...
│
├── Media/HaishinKit/ # Forked streaming engine
│ └── Media/
│ ├── Video/VideoUnit.swift # Camera capture + effects pipeline
│ └── Audio/AudioUnit.swift # Microphone + audio encoding
│
├── GenericLivePlayer/ # Video player for watching streams
├── Obs/ # OBS WebSocket integration
├── RemoteControl/ # Remote control via relay
├── Notify/ # Push notifications
└── Util/ # Keychain, orientation, parsing, etc.
Swae Watch Watch App/ # watchOS companion
├── View/Chat/ # Watch chat display
├── View/Control/ # Stream controls
└── View/Preview/ # Stream preview
Swae Screen Recording/ # ReplayKit extension
├── SampleHandler.swift # Screen capture handler
└── Shared/ # IPC buffer transport
Common/ # Shared utilities
├── Various/ # Audio/video buffer extensions
└── View/ # Shared overlay views
- Singleton Coordinator —
AppCoordinatorinitializes and owns all global state - Observable Objects —
AppState,Model,WalletModeldrive reactive UI via Combine - Actor Concurrency —
NWCClient,BackgroundPersistenceActorfor thread-safe async operations - GPU Pipeline — Video effects chain using
CIFilter.sourceOverCompositing(CIImage) andMTIMultilayerCompositingFilter(MetalPetal) - Strict Threading — encoding on
processorPipelineQueue, chat onnostrChatQueue, audio on lock queue, UI on main thread only - O(1) Deduplication — Set-based duplicate detection for chat messages, zaps, raids, clips
- Trie Search —
SwiftTriefor instant prefix-based search across events, profiles, and live activities
| NIP | Description | Usage |
|---|---|---|
| NIP-01 | Basic protocol | Event creation, relay communication |
| NIP-04 | Encrypted DMs | WebRTC call signaling |
| NIP-16 | Replaceable events | Metadata, follow lists |
| NIP-33 | Parameterized replaceable | Live activities (kind 30311) |
| NIP-40 | Expiration | Event TTL handling |
| NIP-51 | Lists | Mute lists, bookmarks |
| NIP-53 | Live Activities | Stream metadata, chat (1311), raids (1312), clips (1313) |
| NIP-57 | Lightning Zaps | Zap requests and receipts |
| NIP-98 | HTTP Auth | zap.stream API authentication |
| Package | Purpose |
|---|---|
| NostrSDK | Nostr protocol implementation |
| WebRTC | Real-time peer-to-peer communication |
| HaishinKit | RTMP/SRT streaming engine (forked) |
| MetalPetal | GPU image processing |
| Kingfisher | Image caching and loading |
| SDWebImage | Web image loading (WebP) |
| TrueTime | NTP time synchronization |
| SwiftTrie | Prefix search data structure |
| AlertToast | Toast notifications |
Contributions are welcome. To get started:
- Fork the repository
- Create a feature branch (
git checkout -b feature/my-feature) - Make your changes
- Build and test in Xcode
- Commit (
git commit -m 'feat: add my feature') - Push (
git push origin feature/my-feature) - Open a Pull Request
Please follow Conventional Commits for commit messages.
This project is licensed under the GPL-3.0 License. See the LICENSE file for details.
Built by Suhail Saqan.
Swae builds on the work of the Nostr protocol community, the Bitcoin Lightning Network, and open-source projects including HaishinKit, WebRTC, MetalPetal, and NostrSDK.
Stream free. Get paid in Bitcoin. Own your audience.
