Georgii EmelianovEngineering

The Uzori Wire Contract: Record Schema vs Stream Grammar for Video UI (Div-Wrapped Video Tag vs Native Player Components)

When your AI assistant is not just answering in text but streaming native SwiftUI screens via the Uzori SDK, video playback quickly becomes a real design…

iOS engineer comparing div-wrapped video tag vs native SwiftUI VideoPlayer in a server-driven UI architecture.

Overview: Why Video Playback Belongs in the Uzori Wire Contract

When your AI assistant is not just answering in text but streaming native SwiftUI screens via the Uzori SDK, video playback quickly becomes a real design concern.

Disrupted travel flows (rebooking, refunds, disruption explanation) are a good example: sometimes the best answer is a short explainer video, not another wall of text. In our pillar piece — “What are my options now? — rebooking, refunds and the shape of a disruption answer” — we argue the answer should be a structured, operable interface. Here, we’ll zoom into one slice of that interface: how video is represented in the Uzori wire contract.

This comparison article looks at three main patterns:

  • Wrapping a <video> tag inside a generic <div> (web- or WebView-style)
  • Using higher-level native player components (e.g., SwiftUI VideoPlayer)
  • Using specialized server-driven UI player frameworks (Uzori-style record schema + stream grammar)

We’ll evaluate each along three axes:

  • Control customization
  • Performance and accessibility
  • Fit with server-driven UI stream grammar and record schema

The Uzori Wire Contract: Record Schema and Stream Grammar

Before we compare playback options, we need to define the Uzori wire contract.

What is the Uzori record schema?

Think of the record schema as the typed, server-approved description of UI screens that an LLM can compose but your server must validate before anything reaches the device.

In a video context, a record schema might include:

  • VideoBlock(id, source, kind, title, description, posterImage, actions)
  • PlaybackConfig(autoplay, loop, muted, showControls, preferredPlayer)
  • AccessibilityHints(captionTrack, transcriptUrl, ariaLabel)

This echoes how Confluent’s Schema Registry treats data contracts:

  • Versioned types with explicit compatibility modes (backward, forward, full)
  • Quality rules and metadata (owners, SLOs, constraints)

The same discipline applies to a Uzori UI record schema: every video block is a typed capability, not arbitrary JSON.

What is the Uzori stream grammar?

The stream grammar is the serialized, boundary-aware protocol for sending those UI records over the wire and rendering them progressively.

It’s closer to React Server Components’ streaming model than ad-hoc JSON:

  • Only serializable UI records cross the server/client boundary
  • The server can stream UI chunks as they’re ready
  • The client decodes strictly, without executing arbitrary remote code

In the case of video:

  • The grammar controls when the video block appears in the stream
  • It defines how updates (play state, progress, error states) cross the boundary
  • It constrains interaction messages (e.g., seeking, toggling captions) to a safe subset

With this backdrop, we can compare three playback patterns inside that wire contract.

Option 1: Video Tag Inside a Div (Wrapped Web Video)

The simplest pattern in web UI is to put a <video> tag inside a <div> and tweak behavior via attributes and JavaScript.

In a server-driven UI stream grammar, this usually looks like:

  • UI record: { type: "html", tag: "video", wrapper: "div", attrs: {...} }
  • Client: generic HTML renderer (WebView or web container)

Pros

  • Quick to ship if you already use web views
  • Easy to copy-paste existing web player snippets
  • Broad browser-level support for basic controls

Control customization

Custom controls are possible but fully your responsibility:

  • MDN notes that default <video> controls “give you a lot for free,” while custom controls require manual implementation of play/pause, scrubber, volume, captions, keyboard support.
  • W3C warns that building an accessible custom media player demands advanced HTML and JavaScript skills.

In a Uzori-style SDUI setup, this means:

  • Your wire schema now has to model all these ad-hoc controls
  • Your LLM must understand a grab-bag of HTML/JS patterns
  • Your server loses control over accessible defaults

Performance and accessibility

On iOS specifically, WebView video has extra constraints:

  • allowsInlineMediaPlayback is false by default on iPhone and true on iPad
  • Without playsinline, videos must be full-screen on iPhone

This affects the UX dramatically:

  • Inline playback may fail or jump to full-screen unexpectedly
  • Energy usage and performance vary across devices and OS versions

Accessibility challenges:

  • You need to enforce WCAG 2.2 AA target size (at least 24×24 CSS pixels) on custom controls
  • You must manage captions, transcripts, focus order, and keyboard shortcuts yourself

Fit with server-driven UI

From an SDUI perspective, <video> inside <div> is too low-level:

  • Apollo’s SDUI guidance: schemas should expose product-facing capabilities, not raw DOM primitives
  • W3C says most organizations should “use an existing player with good accessibility support,” not hand-roll controls

For Uzori’s wire contract, this approach is:

  • Harder to validate safely on the server
  • Brittle to evolve (HTML attributes and JS behavior change over time)
  • Difficult to align with native app design systems

Option 2: Native Player Components (SwiftUI VideoPlayer)

On iOS 14+, Apple provides VideoPlayer in AVKit — a native playback UI with built-in controls.

This pattern fits Uzori’s native-first, structure-over-chaos philosophy much better.

Pros

  • System-defined controls that match platform expectations
  • Apple explicitly notes that creating the player indirectly helps avoid performance issues and side effects
  • High-quality defaults for playback, scrubbing, fullscreen

Control customization

You can still customize:

  • Surround VideoPlayer with your own SwiftUI layout
  • Overlay buttons for task-specific actions (e.g., “View refund options” after the video explains policy)

But crucially, you don’t implement:

  • Low-level playback state
  • Seek bar behavior
  • Caption toggles

These come from the native component, which matches Apple’s Human Interface Guidelines: use and adapt system-defined components instead of reinventing them.

Performance and accessibility

Performance benefits:

  • Stronger integration with device hardware, energy model, and OS codecs
  • More predictable inline vs full-screen behavior than WebView wrappers

Accessibility benefits:

  • Built-in support for captions, VoiceOver, and platform media controls
  • Easy compliance with W3C’s guidance: use an existing accessible player

Fit with server-driven UI

In a Uzori record schema, VideoPlayer becomes a declarative capability:

  • VideoBlock(kind: .nativePlayer, source: .url(...), accessibilityHints: ...)
  • PlaybackConfig(preferredPlayer: .system)

This type can be:

  • Versioned and validated server-side, like a data contract
  • Resolved client-side to native SwiftUI components

The stream grammar only needs to support:

  • Emitting a VideoBlock record
  • Handling simple playback events (play, pause, finished)

No arbitrary HTML or JavaScript crosses the boundary.

Option 3: Server-Driven Player Frameworks (Uzori-style Generative UI)

The third pattern is specialized server-driven UI for video, where the player is a first-class concept in the Uzori wire contract, not just a generic component.

Here, the Uzori SDK wire format might include:

  • VideoBlock records with strongly typed fields
  • A PlayerLayout record for surrounding chrome (title, description, actions)
  • A StreamEvent grammar for play/pause/progress and analytics

Pros

  • Generative UI, server-driven safety: the LLM composes layouts, your server validates the schema before streaming
  • Consistent use of native SwiftUI controls (e.g., VideoPlayer) or approved variants
  • Rich orchestration with other UI blocks: forms, comparison views, carousels

In a disrupted travel scenario, this lets AI respond with:

  • A short explainer video about rebooking vs refunds
  • A comparison view of options beneath the player
  • A multi-step wizard triggered when the video ends or the user taps a CTA

Control customization

You get the best of both worlds:

  • The core player stays native and accessible
  • Surrounding layout is AI-generated within a constrained schema

The record schema can limit customization to:

  • Allowed overlays (e.g., buttons, chips, segmented controls)
  • Minimum target size (24×24 CSS pixels) for tap targets, per W3C
  • Approved interactions (start refund flow, open FAQ, show transcript)

Performance and accessibility

Because the player is modeled at the schema level:

  • The server can enforce quality rules: captions required, transcripts linked, max auto-play rules
  • The client renders efficient native views, avoiding WebView overhead

DeclarUI research supports this design:

  • Direct multimodal UI generation struggles with component recognition and interaction logic
  • DeclarUI’s compiler-driven pipeline achieved 98% compilation success and up to 55% better visual similarity than state-of-the-art MLLMs

Uzori adopts the same principle: constrain generation through compiler-checkable, typed records.

Fit with server-driven UI

This is where Uzori is strongest:

  • The player is a semantically rich record in the schema
  • The stream grammar has first-class rules for video blocks and events
  • Every screen is validated on the server before streaming into the app

In other words, this is AI-native, UI-first server-driven video, not just a chat answer with a link.

Comparison Table: Video Tag in Div vs Native Player vs Uzori-style Player

Here’s a side-by-side look at the three patterns.

| Criterion | Video tag wrapped in div | Native player component (SwiftUI VideoPlayer) | Server-driven player (Uzori-style) | | --- | --- | --- | --- | | Control customization | High effort, manually implemented, easy to break accessibility | Moderate, via overlays and surrounding SwiftUI layout | High-level, schema-governed; core controls native, overlays constrained | | Accessibility | Must hand-roll captions, keyboard, focus, WCAG target sizes | System-provided accessibility, easy to augment | System accessibility plus schema-level requirements (captions, transcripts) | | iOS performance | Dependent on WebView configuration (allowsInlineMediaPlayback, playsinline) | Optimized native playback, fewer side effects | Same native benefits plus SDUI orchestration; performance predictable | | Fit with SDUI record schema | Weak: represents DOM primitives, hard to validate and evolve | Good: represents a well-known capability (VideoPlayer) | Strong: video is a first-class schema type with versioning, quality rules | | Fit with streaming UI grammar | Requires generic HTML stream, fragile and boundary-heavy | Simple: stream declarative VideoBlock records | Purpose-built stream events for video; clean client/server separation | | Integration in AI flows | AI must emit HTML/JS; harder to reason about correctness | AI emits high-level "show video" intents mapped to schema | AI emits full flows: video + downstream forms, comparisons, wizards |

When to Use Each Pattern

Different teams and products will land in different places. Here’s a practical recommendation.

Use div-wrapped video tags when…

  • You already rely heavily on WebView-based UX
  • You have a mature, accessible web player you want to reuse
  • Your AI integration is primarily web-first, and native consistency is less critical

But for a native iOS product-focused team, this is a stopgap, not a strategic choice.

Use native player components when…

  • You want native UX quality and performance
  • You need to integrate video into existing SwiftUI screens without a full SDUI overhaul
  • You’re building a single feature (e.g., a disruption explainer video) and can curate UI manually

This is the right baseline for most iOS apps.

Use server-driven (Uzori-style) players when…

  • You’re investing in AI-native experiences, not just bolted-on chat
  • You want AI to orchestrate flows: video plus forms, comparison views, and wizards
  • You care about schema governance, safety, and rapid iteration

For teams working on complex flows like travel disruption answers — where video is one piece of a multi-step resolution journey — Uzori’s wire contract is the pattern that scales.

Recommendation for iOS Teams

For the most common iOS use case — a modern SwiftUI app, AI assistant, and server-driven architecture — the clear path is:

  1. Standardize on native player components (SwiftUI VideoPlayer) for core playback.
  2. Model video explicitly in your SDUI record schema (e.g., VideoBlock, PlaybackConfig, AccessibilityHints).
  3. Adopt a stream grammar that treats video as a first-class block with defined events and constraints.
  4. Let Uzori’s AI interface layer generate task-specific flows around that player: disruption explainers, refund vs rebook comparisons, and guided resolution wizards.

Wrapping a <video> tag inside a <div> is fine for web pages, but in an AI-native mobile world, it’s an architectural mismatch. For Uzori and for most iOS engineering teams, the winning pattern is native video inside a structured, server-driven UI contract.

To see how video and other rich blocks fit into a disruption flow end-to-end, read our related guide: “What are my options now? — rebooking, refunds and the shape of a disruption answer.”

FAQ: Video Playback in Uzori’s Wire Contract

1. How does Uzori’s record schema represent a video player?

Uzori treats video as a typed UI capability, not generic HTML.

A typical schema might define a VideoBlock record with:

  • Source (URL, asset ID)
  • Player kind (native, external)
  • Accessibility hints (captions, transcript, labels)
  • Optional overlays (buttons, chips, CTAs)

This record is versioned and validated server-side before being streamed to the client.

2. Why is a streaming UI grammar important for video?

Video introduces time-based interactions: play, pause, seeking, completion, errors.

A streaming UI grammar:

  • Defines which events cross the server/client boundary
  • Ensures only serializable, safe messages are exchanged
  • Allows progressive delivery of UI blocks, similar to React’s streaming server APIs

Without this grammar, you end up with ad-hoc event handling that’s hard to secure and reason about.

3. Is there ever a good reason to use a video tag inside a div in a native app?

Yes, but it’s niche.

It makes sense when:

  • Your app is fundamentally a web container
  • You’re reusing a mature web player with unique features

However, for iOS apps that prioritize native UX and performance, Apple’s own guidance on WKWebView is clear: use web content when web technologies fit better, not by default. For most AI-native experiences, native VideoPlayer inside a structured schema is the better default.

4. How does Uzori ensure accessibility for AI-generated video UI?

Accessibility is baked into the wire contract:

  • Schema fields require captions and transcript links where appropriate
  • Tap targets respect W3C’s 24×24 CSS pixel minimum
  • Native player components provide platform-level accessibility support

Because the server validates every screen, you can enforce rules like “no video block without captions” at the schema layer.

5. How does this relate to disruption flows like rebooking and refunds?

In disruption scenarios, video is often an explanatory layer.

Uzori lets AI:

  • Insert a video block explaining rebooking vs refunds
  • Follow with structured options, forms, and comparison views
  • Orchestrate the full resolution journey as a native, operable UI — not just a chat transcript with a link.

That’s the core of our point of view: AI UX shouldn’t be a chat box pasted on your app; it should be your app’s interface, including how video is embedded and controlled.

← All posts