Skip to content

Video Workouts

Video workouts are launched with StreamingWorkoutController (or a subclass) using the same GraphQL + token flow as classic workouts.

1. Detect video session and launch

swift
if response.data?.publicWorkoutSession.asWorkoutVideoSession != nil {
    let controller = try await SampleStreamingWorkoutController(data: data, token: token)
    controller.modalPresentationStyle = .fullScreen
    present(controller, animated: true)
}

2. Handle async save in a video controller subclass

swift
final class SampleStreamingWorkoutController: StreamingWorkoutController {
    private var savePublisher: AnyPublisher<Void, Never>?

    override func saveSession(state: SaveWorkoutState) {
        super.saveSession(state: state)

        savePublisher = Future<Void, Never> { promise in
            // Replace with your backend persistence.
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                promise(.success(()))
            }
        }.eraseToAnyPublisher()
    }
}

StreamingWorkoutController uses the same completion contract as classic workouts. Override saveSession(state:) to persist completed workout state, quitWorkout() to react when the user exits before completion, and trackEvent(_:properties:) to forward TrainingKit analytics events. Always call super in these overrides so TrainingKit can complete its internal save and teardown behavior.

3. Add cast controls with a remote manager

swift
override func viewDidLoad() {
    super.viewDidLoad()

    let castButton = GCKUICastButton()
    castButton.tintColor = .white
    topLeftStack.addArrangedSubview(castButton)

    let manager = GoogleCastManager(video: video, metadata: metadata)
    remoteManager = manager
}

When Cast support is enabled, the remote manager coordinates playback state between TrainingKit and the cast session.

For complete production setup (Info.plist permissions, GCKCastContext bootstrap, session listeners, and RemoteManager implementation), see Google Cast for Video Workouts.

Source references