Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/sdk-size-metrics.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
runs-on: macos-15
env:
GITHUB_TOKEN: '${{ secrets.CI_BOT_GITHUB_TOKEN }}'
GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
steps:
- name: Connect Bot
uses: webfactory/[email protected]
Expand All @@ -28,10 +29,13 @@ jobs:

- uses: ./.github/actions/bootstrap

- name: Run SDK Size Metrics
- name: Run General SDK Size Metrics
run: bundle exec fastlane show_frameworks_sizes
timeout-minutes: 30
env:
GITHUB_PR_NUM: ${{ github.event.pull_request.number }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APPSTORE_API_KEY: ${{ secrets.APPSTORE_API_KEY }}

- name: Run Detailed SDK Size Metrics
run: bundle exec fastlane size_analyze
timeout-minutes: 30
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ App Thinning Size Report.txt
app-thinning.plist
*.dmg
yeetd-normal.pkg
*LinkMap.txt

# Stream Video Buddy
video-buddy-server.log
Expand Down
3 changes: 2 additions & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ builder:
configs:
- platform: ios
documentation_targets: [StreamVideoSwiftUI, StreamVideoUIKit, StreamVideo]
scheme: StreamChatSwiftUI
scheme: StreamVideoSwiftUI
swift_version: '6.1'

6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

# Upcoming

### 🔄 Changed
- Update WebRTC to 137.0.42 which brings performance improvements on video rendering. [#983](https://github.com/GetStream/stream-video-swift/pull/983)

# [1.34.2](https://github.com/GetStream/stream-video-swift/releases/tag/1.34.2)
_October 24, 2025_

### 🔄 Changed

# [1.34.1](https://github.com/GetStream/stream-video-swift/releases/tag/1.34.1)
Expand Down
9 changes: 8 additions & 1 deletion DemoApp/Sources/Views/StatsView/DemoStatsAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ final class DemoStatsAdapter {
callStatsReportCancellable = call?
.state
.$statsReport
.receive(on: DispatchQueue.main)
.sink { [weak self] in
if let report = $0 { self?.reports.append(report) }
guard let self, let report = $0 else { return }

reports.append(report)

if reports.endIndex > 20 {
_ = reports.dropFirst()
}
}
}
}
Expand Down
9 changes: 7 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,11 @@ GEM
bundler
fastlane
pry
fastlane-plugin-stream_actions (0.3.90)
fastlane-plugin-stream_actions (0.3.101)
xctest_list (= 1.2.1)
fastlane-plugin-versioning (0.7.1)
fastlane-plugin-xcsize (1.1.0)
xcsize (= 1.1.0)
fastlane-sirp (1.0.0)
sysrandom (~> 1.0)
ffi (1.17.2)
Expand Down Expand Up @@ -416,6 +418,8 @@ GEM
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
xcsize (1.1.0)
commander (>= 4.6, < 6.0)
xctest_list (1.2.1)

PLATFORMS
Expand All @@ -429,8 +433,9 @@ DEPENDENCIES
fastlane
fastlane-plugin-create_xcframework
fastlane-plugin-lizard
fastlane-plugin-stream_actions (= 0.3.90)
fastlane-plugin-stream_actions (= 0.3.101)
fastlane-plugin-versioning
fastlane-plugin-xcsize (= 1.1.0)
json
lefthook
plist
Expand Down
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/apple/swift-protobuf.git", exact: "1.30.0"),
.package(url: "https://github.com/GetStream/stream-video-swift-webrtc.git", exact: "137.0.41")
.package(url: "https://github.com/GetStream/stream-video-swift-webrtc.git", exact: "137.0.42")
],
targets: [
.target(
Expand Down
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<a href="https://swift.org"><img src="https://img.shields.io/badge/Swift-5.9%2B-orange.svg" /></a>
</p>
<p align="center">
<img id="stream-video-label" alt="StreamVideo" src="https://img.shields.io/badge/StreamVideo-8.67%20MB-blue"/>
<img id="stream-video-label" alt="StreamVideo" src="https://img.shields.io/badge/StreamVideo-8.71%20MB-blue"/>
<img id="stream-video-swiftui-label" alt="StreamVideoSwiftUI" src="https://img.shields.io/badge/StreamVideoSwiftUI-2.36%20MB-blue"/>
<img id="stream-video-uikit-label" alt="StreamVideoUIKit" src="https://img.shields.io/badge/StreamVideoUIKit-2.48%20MB-blue"/>
<img id="stream-web-rtc-label" alt="StreamWebRTC" src="https://img.shields.io/badge/StreamWebRTC-11.01%20MB-blue"/>
Expand Down Expand Up @@ -247,10 +247,27 @@ Video roadmap and changelog is available [here](https://github.com/GetStream/pro
- [x] Better audio support for livestreams

### 1.5.0 milestone - June
- [] Livestreaming support on 1080p @ 60fps
- [] Distinguish between RTMP and regular tracks
- [] Waiting rooms
- [] Improve visibility on join call issues
- [x] Livestreaming support on 1080p @ 60fps
- [x] Improve visibility on join call issues
- [x] Stats V2
- [x] Configure policies based on the the device's proximity information

### 1.6.0 milestone - September

- [x] Pausing video on low bandwidths
- [x] Distinguish between RTMP and regular tracks
- [x] WHIP
- [x] SRT ingress
- [x] Python RTC SDK (A/V AI integrations)
- [x] TURN/STUN on TCP/UDP 443 and static IP ranges

### 1.7.0 milestone - December

- [] Hifi Audio
- [] Screensharing Audio
- [] Battery usage improvements
- [] Swift 6.2 support
- [] RTMP streaming from device

### After 1.5.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Foundation

extension SystemEnvironment {
/// A Stream Video version.
public static let version: String = "1.34.1"
public static let version: String = "1.34.2"
/// The WebRTC version.
public static let webRTCVersion: String = "137.0.41"
public static let webRTCVersion: String = "137.0.42"
}
2 changes: 1 addition & 1 deletion Sources/StreamVideo/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.34.1</string>
<string>1.34.2</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
Expand Down
2 changes: 2 additions & 0 deletions Sources/StreamVideo/StreamVideo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class StreamVideo: ObservableObject, @unchecked Sendable {
@Injected(\.callCache) private var callCache
@Injected(\.screenProperties) private var screenProperties
@Injected(\.audioStore) private var audioStore
@Injected(\.battery) private var battery

private enum DisposableKey: String { case ringEventReceived }

Expand Down Expand Up @@ -203,6 +204,7 @@ public class StreamVideo: ObservableObject, @unchecked Sendable {
// Warm up
_ = eventNotificationCenter
_ = idleTimerAdapter
_ = battery

if user.type != .anonymous {
let userAuth = UserAuth { [weak self] in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ extension AudioProcessingStore.Namespace {
file: StaticString,
function: StaticString,
line: UInt
) throws -> AudioProcessingStore.Namespace.StoreState {
) async throws -> AudioProcessingStore.Namespace.StoreState {
var updatedState = state

switch action {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ extension StreamCallAudioRecorder.Namespace {
file: StaticString,
function: StaticString,
line: UInt
) throws -> State {
) async throws -> State {
var updatedState = state

switch action {
Expand Down
123 changes: 123 additions & 0 deletions Sources/StreamVideo/Utils/Battery/BatteryStore.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import Combine
import Foundation
#if canImport(UIKit)
import UIKit
#endif

/// Monitors the device battery state and exposes the latest readings through
/// the shared store pipeline.
final class BatteryStore: CustomStringConvertible, @unchecked Sendable {

var state: Namespace.State { store.state }

var description: String {
var result = "Battery {"
result += " isMonitoring:\(store.state.isMonitoringEnabled)"
result += " state:\(store.state.state)"
result += " level:\(store.state.level)"
result += " }"
return result
}

private let store: Store<Namespace>
private let disposableBag = DisposableBag()

init(
store: Store<Namespace> = Namespace.store(
initialState: .init(
isMonitoringEnabled: false,
state: .unknown,
level: 0
)
)
) {
self.store = store

self.store.dispatch(.setMonitoringEnabled(true))

#if canImport(UIKit)
self.store
.publisher(\.isMonitoringEnabled)
.filter { $0 }
.removeDuplicates()
.receive(on: DispatchQueue.main)
.map { _ in
MainActor.assumeIsolated {
(
UIDevice.current.batteryState,
UIDevice.current.batteryLevel
)
}
}
.sink { [weak self] stateAndLevel in
let (state, level) = stateAndLevel
self?.store.dispatch([
.setState(.init(state)),
.setLevel(level)
])
}
.store(in: disposableBag)
#endif
}

func publisher<V: Equatable>(
_ keyPath: KeyPath<Namespace.State, V>
) -> AnyPublisher<V, Never> {
store.publisher(keyPath)
}

func dispatch(
_ actions: [Namespace.Action],
file: StaticString = #file,
function: StaticString = #function,
line: UInt = #line
) -> StoreTask<Namespace> {
store.dispatch(
actions,
file: file,
function: function,
line: line
)
}
}

extension BatteryStore: Encodable {
private enum CodingKeys: String, CodingKey {
case isMonitoringEnabled
case state
case level
}

/// Encodes a snapshot of the store's observable state.
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
let state = store.state
try container.encode(
state.isMonitoringEnabled,
forKey: .isMonitoringEnabled
)
try container.encode(state.state, forKey: .state)
try container.encode(state.level, forKey: .level)
}
}

extension BatteryStore: InjectionKey {
/// The default recorder instance used when no custom recorder is
/// provided.
nonisolated(unsafe) static var currentValue: BatteryStore = .init()
}

extension InjectedValues {
var battery: BatteryStore {
get {
Self[BatteryStore.self]
}
set {
Self[BatteryStore.self] = newValue
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import Foundation

extension BatteryStore.Namespace {
/// Actions that drive battery monitoring state transitions.
///
/// These actions mirror updates from `UIDevice` and user controlled
/// monitoring preferences.
enum StoreAction: Sendable, Equatable, StoreActionBoxProtocol {
case setMonitoringEnabled(Bool)
case setLevel(Float)
case setState(StoreState.BatteryState)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Copyright © 2025 Stream.io Inc. All rights reserved.
//

import Foundation

extension BatteryStore {

/// Namespace configuration for the battery monitoring store.
enum Namespace: StoreNamespace {

/// The state type for this store namespace.
typealias State = StoreState

/// The action type for this store namespace.
typealias Action = StoreAction

/// Unique identifier for this store instance.
///
/// Used for logging and debugging purposes.
static let identifier: String = "battery.store"

static func reducers() -> [Reducer<Namespace>] {
[
DefaultReducer()
]
}

static func middleware() -> [Middleware<BatteryStore.Namespace>] {
[
ObservationMiddleware()
]
}
}
}
Loading
Loading