Documentation clarity for URL playback: KeplerVideoView vs KeplerVideoSurfaceView

App Name: Orchestra Lens

SDK version you are referring to for this feature request: Vega v0.23 / v0.24
React Native version you are referring for this feature request: React Native Kepler 4.0.1 (RN 0.83.0)

App Link on Amazon Appstore (found through Developer Console > Actions column in App List > View on Amazon.com): N/A — hackathon prototype, not yet published

Is your feature request related to a problem?

While implementing URL-based MP4 playback for a Fire TV hackathon project, I found it difficult to determine the recommended video rendering pattern from the Vega documentation.
Some documentation examples use VideoPlayer + KeplerVideoView, while other pages describe KeplerVideoSurfaceView with setSurfaceHandle(). The KeplerVideoSurfaceView API documentation also appears to describe it mainly in the context of pre-buffering / multiple-player scenarios, while newer documentation uses it for ordinary URL playback.
My environment is React Native Kepler 4.0.1 (RN 0.83.0) with @amazon-devices/react-native-w3cmedia 2.3.2.
This made it difficult to identify which implementation should be treated as the recommended reference pattern.

(Write your answer here.)

Describe the solution you’d like

Please add a version-specific compatibility/reference table for Vega media playback that clearly shows:
when to use KeplerVideoView
when to use KeplerVideoSurfaceView
when setSurfaceHandle() is required
the recommended pattern for ordinary URL playback
the recommended pattern for MSE playback
the recommended pattern for pre-buffering / multiple players
whether any of these approaches are legacy or deprecated
It would also help if the implementation guides and API reference pages cross-linked to one canonical example for each supported Vega version.

(Describe your proposed solution here.)

Is this a blocker? Describe alternatives you’ve considered

This was not ultimately a blocker, but it caused substantial debugging time.
My application initially returned MEDIA_ERR_SRC_NOT_SUPPORTED (code 4). To isolate the issue, I created minimal playback tests and compared the different documented rendering approaches.
I then installed Java 21, built Amazon’s unmodified vega-video-sample, and confirmed that the official sample successfully plays video in the same Vega Virtual Device.
My workaround is to use the working official sample as the reference implementation and compare my application against it rather than relying on individual documentation pages alone.

(Write your answer here.)

Additional context

This was encountered while building Orchestra Lens for the Build, Ship, Shape Amazon Developer Hackathon.
Environment:
Apple Silicon Mac
Vega Virtual Device
React Native Kepler 4.0.1 / RN 0.83.0
@amazon-devices/react-native-w3cmedia 2.3.2
Java 21
Amazon’s unmodified vega-video-sample successfully builds and plays video in this environment, so I am not reporting that Vega video playback itself is broken. The request is specifically for clearer, version-specific guidance about the recommended media rendering architecture.

(Write your answer here.)

Hi @atsushiyago

Welcome to the Amazon Developer Community!!

Good news: for your use case there is a single recommended pattern, and it’s the one the official sample uses. Here’s the canonical guidance for RN Kepler 4.0.1 / RN 0.83 on Vega 0.24:
For ordinary URL-based MP4 playback (your case):
Use URL Mode with VideoPlayer + KeplerVideoSurfaceView from @amazon-devices/react-native-w3cmedia, connected via setSurfaceHandle(). This is the recommended reference pattern. The flow:

  1. Render a KeplerVideoSurfaceView.
  2. In its onSurfaceViewCreated(surfaceHandle) callback: await video.initialize() → video.setSurfaceHandle(surfaceHandle) → set autoplay → set video.src = <your .mp4 url>.
  3. In onSurfaceViewDestroyed(surfaceHandle): clearSurfaceHandle() → deinitialize() → clean up the ref.

Full working example: Selecting the Playback Mode - Vega 0.24 (see “Video Playback Example” under URL Mode).

On KeplerVideoView vs KeplerVideoSurfaceView (the ambiguity you hit):
Both are components in @amazon-devices/react-native-w3cmedia, and neither is deprecated - but they’re at different levels:

  • KeplerVideoSurfaceView is the lower-level surface component where you manage the
    surface yourself (onSurfaceViewCreated + setSurfaceHandle()). This is the pattern the current 0.24 docs and the official sample use.
  • KeplerVideoView is an older higher-level convenience wrapper that composites KeplerVideoSurfaceView + captions + media-controls UI (you just pass it videoPlayer=). It shows up in the older media-player overview examples. It works, but for RN 0.83 / w3cmedia 2.x I’d standardize on the KeplerVideoSurfaceView pattern to match the sample and avoid surface-lifecycle surprises.

You’re seeing two different patterns across doc pages precisely because the overview page uses KeplerVideoView while the playback-mode page uses KeplerVideoSurfaceView - I’m working with our internal teams on this inconsistency.

Clarifying the surface requirement:

  • setSurfaceHandle() is always required for video when you use KeplerVideoSurfaceView - this is the most likely cause of your MEDIA_ERR_SRC_NOT_SUPPORTED (code 4): if src is set without the surface handle connected, or the codec isn’t supported, you’ll hit that. For MP4, use H.264 video + AAC audio.

Quick reference - what to use when:

  • MP4 / MP3 flat file from URL (your case) → URL Mode → VideoPlayer + KeplerVideoSurfaceView + setSurfaceHandle()
  • HLS / DASH adaptive streaming → MSE Mode → same surface setup + a JS player (Shaka / hls.js / dash.js)
  • DRM / live streaming → MSE Mode → MSE + JS player (URL Mode not supported)
  • Audio-only → URL Mode → VideoPlayer (audio), no surface view needed

Note: URL Mode is only for non-adaptive content - for HLS/DASH you must use MSE Mode with a JS player library.

Warm Regards,
Ivy

Hi Ivy,

Thank you — this clears up the documentation ambiguity very well.

One clarification about my actual implementation: the final application is
audio-only rather than MP4 video. It plays an AAC-LC .m4a file from an HTTPS
CloudFront URL.

So based on your quick reference, my final setup should simply be:

URL Mode
→ VideoPlayer
→ no KeplerVideoSurfaceView / surface handle required

That matches what I am currently using successfully.

The distinction between the overview example using KeplerVideoView and the
playback-mode example using KeplerVideoSurfaceView was exactly the confusing
part, so it is very helpful to know that this documentation inconsistency is
being addressed.

Thank you again for the clarification.

Best,
Atsushi