Skip to content

Conversation

@ipavlidakis
Copy link
Contributor

@ipavlidakis ipavlidakis commented Jul 14, 2025

🔗 Issue Links

Resolves https://linear.app/stream/issue/IOS-994/featureinbound-video-pause

🎯 Goal

Provide a way for the SFU to instruct the client which tracks are remotely paused.

📝 Summary

Docs preview: https://github.com/GetStream/docs-content/pull/452

🧪 Manual Testing Notes

  • By default the feature is disabled
  • Enter a call with another client
  • Activate the Link conditioner to Edge
  • Remain in the call a few seconds
  • You shouldn't observe any changes during the call. Remote track should be lagging but always visible
  • Disable the link conditioner
  • Logout and enable the feature from the debug menu (Client Capabilities > Subscriber video pause)
  • Enter a call with another client
  • Activate the Link conditioner to Edge
  • Remote track should get disabled at some point (it's ok if it gets reenabled)

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change follows zero ⚠️ policy (required)
  • This change should receive manual QA
  • Changelog is updated with client-facing changes
  • New code is covered by unit tests
  • Comparison screenshots added for visual changes
  • Affected documentation updated (tutorial, CMS)
@ipavlidakis ipavlidakis self-assigned this Jul 14, 2025
@ipavlidakis ipavlidakis requested a review from a team as a code owner July 14, 2025 15:48
@ipavlidakis ipavlidakis added the enhancement New feature or request label Jul 14, 2025
@github-actions
Copy link

Public Interface

+ public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async
@github-actions
Copy link

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Jul 14, 2025

SDK Size

title develop branch diff status
StreamVideo 8.06 MB 8.08 MB +19 KB 🟢
StreamVideoSwiftUI 2.27 MB 2.29 MB +16 KB 🟢
StreamVideoUIKit 2.4 MB 2.41 MB +16 KB 🟢
StreamWebRTC 9.85 MB 9.85 MB 0 KB 🟢
@ipavlidakis ipavlidakis force-pushed the enhancement/incoming-video-pause branch from 58c8bc0 to 1cc43aa Compare July 15, 2025 08:06
@github-actions
Copy link

Public Interface

+ public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause + public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant
@github-actions
Copy link

Public Interface

+ public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async
Copy link
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have this on by default, without it, it breaks the experience on low-end networks. We can offer an opt out if needed.

@ipavlidakis
Copy link
Contributor Author

We should have this on by default, without it, it breaks the experience on low-end networks. We can offer an opt out if needed.

There is opt-out as integrators can simply pass an empty array for the clientCapabilities. Let me align that with React too.

@ipavlidakis ipavlidakis force-pushed the enhancement/incoming-video-pause branch from fee2556 to d65a70a Compare July 15, 2025 10:09
Copy link
Contributor

@martinmitrevski martinmitrevski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good codewise ✅ Let's test it a bit and also check the failing tests.

@github-actions
Copy link

Public Interface

+ extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self + public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async
@ipavlidakis ipavlidakis force-pushed the enhancement/incoming-video-pause branch from d65a70a to 6d66e1f Compare July 15, 2025 11:28
@github-actions
Copy link

Public Interface

+ public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause + extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async
@github-actions
Copy link

Public Interface

+ extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self + public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func updateClientCapabilities(_ clientCapabilities: Set<ClientCapability>)async
@github-actions
Copy link

Public Interface

+ public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause + extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self public class Call: @unchecked Sendable, WSEventsSubscriber + public func enableClientCapabilities(_ capabilities: Set<ClientCapability>)async  + public func disableClientCapabilities(_ capabilities: Set<ClientCapability>)async public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant
@ipavlidakis ipavlidakis force-pushed the enhancement/incoming-video-pause branch from 9e6ad49 to 4883ad4 Compare July 17, 2025 11:00
@github-actions
Copy link

Public Interface

+ extension TrackType  +  + public static let audio: Self + public static let video: Self + public static let screenshare: Self + public struct TrackType: RawRepresentable, Codable, Hashable, ExpressibleByStringLiteral, Sendable  +  + public let rawValue: String +  +  + public init(rawValue: String) + public init(stringLiteral value: String) + public enum ClientCapability: Hashable, Sendable, CaseIterable  +  + case subscriberVideoPause public struct CallParticipant: Identifiable, Sendable, Hashable - public var userId: String + public var pausedTracks: Set<TrackType> - public var name: String + public var userId: String - public var profileImageURL: URL? + public var name: String - public var isPinned: Bool + public var profileImageURL: URL? - public var isPinnedRemotely: Bool + public var isPinned: Bool - public var shouldDisplayTrack: Bool + public var isPinnedRemotely: Bool -  + public var shouldDisplayTrack: Bool -  +  - public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?) +  -  + public init(id: String,userId: String,roles: [String],name: String,profileImageURL: URL?,trackLookupPrefix: String?,hasVideo: Bool,hasAudio: Bool,isScreenSharing: Bool,showTrack: Bool,track: RTCVideoTrack? = nil,trackSize: CGSize = CGSize(width: 1024, height: 720),screenshareTrack: RTCVideoTrack? = nil,isSpeaking: Bool = false,isDominantSpeaker: Bool,sessionId: String,connectionQuality: ConnectionQuality,joinedAt: Date,audioLevel: Float,audioLevels: [Float],pin: PinInfo?,pausedTracks: Set<TrackType>) -  +  - public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool +  - public func withUpdated(trackSize: CGSize)-> CallParticipant + public static func ==(lhs: CallParticipant,rhs: CallParticipant)-> Bool - public func withUpdated(track: RTCVideoTrack?)-> CallParticipant + public func withUpdated(trackSize: CGSize)-> CallParticipant - public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant + public func withUpdated(track: RTCVideoTrack?)-> CallParticipant - public func withUpdated(audio: Bool)-> CallParticipant + public func withUpdated(screensharingTrack: RTCVideoTrack?)-> CallParticipant - public func withUpdated(video: Bool)-> CallParticipant + public func withUpdated(audio: Bool)-> CallParticipant - public func withUpdated(screensharing: Bool)-> CallParticipant + public func withUpdated(video: Bool)-> CallParticipant - public func withUpdated(showTrack: Bool)-> CallParticipant + public func withUpdated(screensharing: Bool)-> CallParticipant - public func withUpdated(trackLookupPrefix: String)-> CallParticipant + public func withUpdated(showTrack: Bool)-> CallParticipant - public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant + public func withUpdated(trackLookupPrefix: String)-> CallParticipant - public func withUpdated(dominantSpeaker: Bool)-> CallParticipant + public func withUpdated(isSpeaking: Bool,audioLevel: Float)-> CallParticipant - public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(dominantSpeaker: Bool)-> CallParticipant - public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withUpdated(connectionQuality: ConnectionQuality)-> CallParticipant + public func withUpdated(pin: PinInfo?)-> CallParticipant + public func withPausedTrack(_ trackType: TrackType)-> CallParticipant + public func withUnpausedTrack(_ trackType: TrackType)-> CallParticipant public class Call: @unchecked Sendable, WSEventsSubscriber + public func enableClientCapabilities(_ capabilities: Set<ClientCapability>)async  + public func disableClientCapabilities(_ capabilities: Set<ClientCapability>)async
@ipavlidakis ipavlidakis merged commit f60e3bd into develop Jul 18, 2025
12 checks passed
@ipavlidakis ipavlidakis deleted the enhancement/incoming-video-pause branch July 18, 2025 14:02
@Stream-SDK-Bot Stream-SDK-Bot mentioned this pull request Jul 21, 2025
@Stream-SDK-Bot Stream-SDK-Bot mentioned this pull request Jul 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

4 participants