Bản lưu ngày / Snapshot of 2026-10-20 · Xem bản mới nhất / See the latest version
WanduraDocsBeta
BetaThese docs are in beta and change often. Something wrong, unclear or missing? Tell us.
You are reading an older version of these docs: v1 · Go to the latest (v2)
Change history

History: Player SDK on iOS

Every change to this page, newest first. Expand an entry to see what changed.

← Player SDK on iOS

  1. 2 Oct 2026 · +55 −56 lines
    Show changes
    - // Wandura playback in an iOS app (Swift 5.9+, iOS 15+). Reviewed by hand: the docs CI runs `swiftc -parse` on this
    - // file when the runner has a Swift toolchain, and always checks that brackets balance.
    - // Guide: https://docs.wandura.ai/developers/player-sdk/ios
    - //
    - // The app never talks to Wandura and never holds an API key. It talks to YOUR backend, which applies your paywall
    - // and asks Wandura for tickets. Only `PlayerSDK` touches the Player SDK: fill it in with the calls named in the
    - // Player SDK guide (partner.wandura.ai → Developers → Player SDK).
    - import Foundation
    + # Player SDK on iOS
      
    - // #region sdk
    + > **TL;DR** — Install `TTSDKFramework` `1.52.100.4-standard` with CocoaPods (iOS 11+, Xcode 14+, Bitcode off), add the licence file Wandura sends you, start the SDK, and read the two device values after the licence check passes. Your app sends them to **your** backend, gets a ticket back, and gives the ticket to the SDK. On an SDK error, ask for **one** fresh ticket and resume.
    + 
    + ## Prerequisites {#prerequisites}
    + 
    + | | |
    + |---|---|
    + | Licence | The `.lic` file and App ID from Wandura, bound to your **final** bundle ID. See [Player SDK](index.md#licence). |
    + | Toolchain | Xcode 14 or later, iOS 11.0 or later, Bitcode disabled, CocoaPods (always open the `.xcworkspace`). |
    + | Devices | A real iPhone for encrypted playback. |
    + | Your backend | A ticket endpoint: [Playback flow and paywall](../guides/playback-flow.md). |
    + 
    + The exact SDK calls (start-up, licence notification, device values, playback, subtitles) are in the Player SDK guide on partner.wandura.ai → **Developers** → **Player SDK**.
    + 
    + ## The flow in your app {#flow}
    + 
    + 1. **Start the SDK** at launch with your App ID and licence file, and wait for the licence result before anything else.
    + 2. **Read the device values** (device ID → `union_info`, device public key → `drm_kek`). Never send `nil`, `"(null)"` or an empty string: throw instead.
    + 3. **Ask your backend** to play the episode. Your backend applies your paywall and asks Wandura; your app never holds an API key.
    + 4. **Play**: give `vid` and `play_auth_token` to the SDK; add the subtitles.
    + 5. **Preload** the next episodes with the prefetched tickets your backend returns.
    + 6. **On any SDK error** (an expired ticket included): request **one** fresh ticket and resume at the same position. Do not branch on SDK error codes, and do not loop.
    + 7. **Back from the background**: if the current ticket has less than a minute left, replace it before resuming.
    + 
    + ## Code {#code}
    + 
    + The file below is the app side of that flow, in Swift. Only `PlayerSDK` touches the SDK: fill it in with the calls from the portal guide. Your backend's response shape matches the [Node and Python backend examples](../guides/playback-flow.md#code).
    + 
    + ### The SDK behind one protocol {#code-sdk}
    + 
    + ```swift
      struct DeviceValues {
          let unionInfo: String // device ID generated by the Player SDK
    ⋯
          var onError: ((Error) -> Void)? { get set }
      }
    - // #endregion sdk
    - 
    - // #region contract
    - struct Subtitle: Decodable {
    -     let lang: String
    -     let url: URL
    -     let format: String
    - }
    - 
    - struct Ticket: Decodable {
    -     let vid: String
    -     let playAuthToken: String // memory only: never log it, never write it to disk
    -     let expiresAt: Date
    -     let subtitles: [Subtitle]
    - 
    -     enum CodingKeys: String, CodingKey {
    -         case vid, subtitles
    -         case playAuthToken = "play_auth_token"
    -         case expiresAt = "expires_at"
    -     }
    - 
    -     /// Wandura's clock decides; allow a minute for a device clock that runs slow.
    -     var isFresh: Bool { expiresAt.timeIntervalSinceNow > 60 }
    - }
    - 
    - struct NextTicket: Decodable {
    -     let episodeNo: Int
    -     let ticket: Ticket
    -     enum CodingKeys: String, CodingKey { case ticket, episodeNo = "episode_no" }
    - }
    - 
    - enum Outcome: String, Decodable {
    -     case locked, unavailable, busy, broken
    -     case notReady = "not_ready"
    - }
    + ```
      
    - /// The shape the example backends (Node, Python) return from YOUR `POST /v1/play`.
    - struct PlayResponse: Decodable {
    -     let ok: Bool
    -     let current: Ticket?
    -     let next: [NextTicket]?
    -     let outcome: Outcome?
    - }
    - // #endregion contract
    + ### Calling your backend {#code-backend}
      
    - // #region backend
    + ```swift
      final class Backend {
          private let baseURL: URL
    ⋯
          }
      }
    - // #endregion backend
    + ```
      
    - // #region controller
    + ### Start, prefetch, expiry, errors {#code-controller}
    + 
    + ```swift
      enum ScreenState {
          case loading
    ⋯
          }
      }
    - // #endregion controller
    + ```
    + 
    + ## Checklist {#checklist}
    + 
    + - [ ] The licence result is checked before device values are read.
    + - [ ] Device values are never `nil`, `"(null)"` or empty when sent.
    + - [ ] The app holds no `wnd_live_` key (search the built `.ipa`).
    + - [ ] `play_auth_token` is kept in memory only: not in `UserDefaults`, logs or crash reports.
    + - [ ] An SDK error leads to one fresh ticket and a resume, never a loop.
    + - [ ] Resuming after more than 29 minutes in the background replaces the ticket first.
    + - [ ] An episode without subtitles plays without an error.
    + 
    + ## Related {#related}
    + 
    + - [Player SDK overview and licence](index.md)
    + - [Smooth playback under load](../guides/smooth-playback.md#in-the-app)
    + - [Subtitles](../guides/subtitles.md)
  2. 2 Oct 2026 · Page created
↑↓ selectEnter openEsc close

Send feedback

Your message goes straight to the Wandura team. It includes the address of this page.

0 / 4000