Bug Description
1. Summary
Alexa voice transport control commands (Play / Pause / Stop / TogglePlayPause / FastForward / Rewind) are never delivered to the app’s JS-side IMediaControlHandlerAsync handler (e.g. a subclass of KeplerMediaControlHandler) when the app uses @amazon-devices/react-native-w3cmedia and registers its handler via player.setMediaControlFocus(componentInstance, handler). The underlying MediaPlayerMPBImpl::pauseInternal() is also never invoked from any Alexa command. As a result, voice transport control is fully non-functional in apps that follow the documented W3C Media KMC integration path.
App Name: Internal Vega OS / Fire TV app (in development, not yet on Amazon Appstore)
App Link on Amazon Appstore: N/A (pre-release, sideloaded VPKG for QA)
Bug Severity: Select one that applies
- Impacts operation of app
- Blocks current development
- Improvement suggestion
- Issue with documentation
- Other
2. Steps to Reproduce
- Build a Vega app that uses
@amazon-devices/react-native-w3cmedia(VideoPlayer) for playback. - Configure
manifest.tomlexactly as invega-audio-sample— includingcategories = ["com.amazon.category.kepler.media"],[[needs.module]] /com.amazon.kepler.media.control.server@IMediaControlServerComponentAsync, and[[extras.value.application.interface]]withinterface_name = "com.amazon.kepler.media.IMediaPlaybackServer",command_optionsandfeatures. - Implement a
KeplerMediaControlHandlersubclass that overrideshandlePlay,handlePause,handleStop,handleTogglePlayPause,handleFastForward,handleRewind,handleGetMetadataInfo,handleGetSessionStateand adds aconsole.logto each. - Pass the handler instance via
player.setMediaControlFocus(componentInstance, new MyHandler())beforeplayer.initialize(). - Sideload the VPKG to a Fire TV device, launch the app, and start any video playback.
- Press the voice button on the remote and say:
- “Alexa, pause” / 「Alexa、一時停止」
- “Alexa, play” / 「Alexa、再生」
- “Alexa, stop” / 「Alexa、停止」
- Observe the device log via
vega device start-log-stream.
3. Observed Behavior
No transport control handler is ever invoked from JS, even though wakeword detection and metadata/session-state handlers do work.
Counters from a 25-minute device session (3 ALEXA_SPEECH_START events for voice commands + normal playback):
| Handler | JS invocation count |
|---|---|
handleGetMetadataInfo |
1 |
handleGetSessionState |
5 |
handlePlay |
0 |
handlePause |
0 |
handleStop |
0 |
handleTogglePlayPause |
0 |
handleFastForward |
0 |
handleRewind |
0 |
Concurrent system events captured in the same session:
| Event | Count |
|---|---|
ALEXA_SPEECH_START / ALEXA_SPEECH_STOP |
4 / 2 |
chromium kepler_media_control_handler.cc(263): handleGetMetadataInfo is not supported warnings |
135 |
MediaPlaybackCluster.cpp:540 command id: 303497224 / 303497222 (cluster polling) |
many |
MediaPlayerMPBImpl::pauseInternal() |
0 |
MediaPlayerMPBImpl::playInternal() (Alexa-originated) |
0 (only audio-focus restoration events) |
User-facing behavior when speaking to Alexa during VOD playback:
| Utterance | Alexa response | App behavior |
|---|---|---|
| “Alexa, pause” / 「Alexa、一時停止」 | silent (no response) | no playback change |
| “Alexa, play” / 「Alexa、再生」 | silent (no response) | no playback change |
| “Alexa, stop” / 「Alexa、停止」 | “現在アクセスできません” (English equivalent: “Sorry, I can’t access this right now”) | no playback change |
The same app on Fire OS handles all of these commands correctly via Android MediaSession.
4. Expected Behavior
Per the W3C Media integration with Vega Media Controls docs:
“Apps that use the W3C Media API to play their content can now get the KMC integration for free for basic playback controls such as pause, play, and seek.”
Either:
- (a) The W3C Media default native handler should pause/resume the
MediaPlayerMPBImplpipeline directly when Alexa sends a Pause/Play command (causingpauseInternal()/playInternal()to fire), OR - (b) The override handler passed to
setMediaControlFocus()should have itshandlePlay/handlePause/handleStop/handleTogglePlayPausemethods invoked.
Neither happens.
4.a Possible Root Cause & Temporary Workaround
The chromium-side warning kepler_media_control_handler.cc(263): handleGetMetadataInfo is not supported firing 135 times per session strongly suggests that the W3C Media internal native handler intercepts most KMC requests in chromium-land and never bridges them to JS. Only specific code paths (1 metadata call and 5 session-state calls in our test) reach JS. Transport control commands never reach JS, and the native handler also fails to drive the underlying MediaPlayerMPBImpl.
Attempted workarounds (none resolved the issue):
- Added
[[needs.module]]forIMediaControlServerComponentAsync(matching sample app). - Explicit
command_options = ["Play","Pause","StartOver","Previous","Next","SkipForward","SkipBackward"]andfeatures = ["AdvancedSeek","VariableSpeed","AudioTracks","TextTracks"]declarations. - Added
@amazon-devices/kepler-media-controls/kepler-media-typesas explicitpackage.jsondependencies. - Overrode
handlePlay/handlePause/handleStopto callplayer.play()/player.pause()on the W3CVideoPlayerdirectly instead of delegating tosuper. - Overrode
handleGetMetadataInfoto return validIMediaMetadata(mediaId + title + empty artwork).
Tried overriding handleGetSessionState to inject mediaInfo, but this caused chromium-side errors:
ERROR:kepler_media_control_manager.cc(154)] Failed with error: [com.amazon.apmf.ForeignRuntimeError]: time instant cannot be represented in epoch-us
likely because the base session-state returned by MediaControlStateUtil.getServerState() contains an uninitialized/invalid ITimeValue for playbackPosition.updatedAtTime. Reverted this override.
No JS-side workaround has been found, since transport control commands never reach the JS handler.
5. Logs or crash report
We can attach the full vega device start-log-stream capture (≈80,000 lines, ~25 min session) on request. Sample excerpt around an Alexa speech event:
03:49:49.258 ALEXA_SPEECH_START
03:49:49.378 W3CMEDIA Handling State change PLAYING → PAUSED (audio focus ducking by Alexa)
03:49:52.368 ALEXA_SPEECH_START (another utterance)
03:49:52.931 MediaPlayerMPBImpl::playInternal mState = 2 (audio focus restoring after Alexa, NOT from a Pause/Play command)
03:49:53.085 ALEXA_SPEECH_STOP
03:49:55.823 ALEXA_SPEECH_START (user said "Alexa, pause")
03:49:58.638 ALEXA_SPEECH_START
03:49:59.317 ALEXA_SPEECH_STOP
// No [KMC] handlePause / handlePlay / handleStop logs anywhere
// No pauseInternal() call
Repeated chromium warning throughout the entire session (135x):
W chromium:[2:26:...]:WARNING:kepler_media_control_handler.cc(263)] handleGetMetadataInfo is not supported
6. Environment
- SDK Version:
vega --version→Active SDK Version: 0.22.6759,Vega CLI Version: 1.2.18 - App State: Foreground (actively playing video during voice command)
- OS Information: Unable to obtain —
vega exec vda -s G0733M08526300QC shell cat /etc/os-releasefails withError: No running instances of com.amazon.dev.shell.service foundon this device. From device logs the hostname isfirestick-076be8a191c3613c. Device serial:G0733M08526300QC(Fire TV Stick on Vega OS).
7. Example Code Snippet / Screenshots / Screengrabs
manifest.toml (matches vega-audio-sample):
schema-version = 1
[package]
title = "Alexa KMC Repro"
id = "com.example.kmcrepro"
version = "1.0.0"
icon = "@image/app_icon.png"
[components]
[[components.interactive]]
id = "com.example.kmcrepro.main"
runtime-module = "/com.amazon.kepler.keplerscript.runtime.loader_2@IKeplerScript_2_0"
categories = ["com.amazon.category.main", "com.amazon.category.kepler.media"]
launch-type = "singleton"
[needs]
[[needs.module]]
id = "/com.amazon.kepler.media.control.server@IMediaControlServerComponentAsync"
[wants]
[[wants.service]]
id = "com.amazon.media.server"
[[wants.service]]
id = "com.amazon.media.playersession.service"
[[wants.service]]
id = "com.amazon.mediabuffer.service"
[[wants.service]]
id = "com.amazon.mediatransform.service"
[[wants.service]]
id = "com.amazon.mediametrics.service"
[[wants.service]]
id = "com.amazon.audio.stream"
[[wants.service]]
id = "com.amazon.audio.control"
[[wants.service]]
id = "com.amazon.audio.system"
[offers]
[[offers.service]]
id = "com.amazon.gipc.uuid.*"
[[extras]]
key = "interface.provider"
component-id = "com.example.kmcrepro.main"
[[extras.value.application.interface]]
interface_name = "com.amazon.kepler.media.IMediaPlaybackServer"
command_options = ["Play", "Pause", "StartOver", "Previous", "Next", "SkipForward", "SkipBackward"]
features = ["AdvancedSeek", "VariableSpeed", "AudioTracks", "TextTracks"]
kepler exec vpt validate manifest.toml → manifest.toml is valid, manifest validation found 0 errors.
LoggingMediaControlHandler.ts (instrumented handler):
import { KeplerMediaControlHandler } from '@amazon-devices/react-native-w3cmedia'
import type {
IMediaMetadata,
IMediaSessionId,
ICommandContext,
} from '@amazon-devices/kepler-media-controls'
import type { MediaId } from '@amazon-devices/kepler-media-types'
export class LoggingMediaControlHandler extends KeplerMediaControlHandler {
async handlePlay(_sessionId?: IMediaSessionId) {
console.log('[KMC] handlePlay called')
return super.handlePlay(_sessionId)
}
async handlePause(_sessionId?: IMediaSessionId, _context?: ICommandContext) {
console.log('[KMC] handlePause called')
return super.handlePause(_sessionId, _context)
}
async handleStop(_sessionId?: IMediaSessionId) {
console.log('[KMC] handleStop called')
return super.handleStop(_sessionId)
}
async handleTogglePlayPause(_sessionId?: IMediaSessionId) {
console.log('[KMC] handleTogglePlayPause called')
return super.handleTogglePlayPause(_sessionId)
}
async handleFastForward(_sessionId?: IMediaSessionId) {
console.log('[KMC] handleFastForward called')
return super.handleFastForward(_sessionId)
}
async handleRewind(_sessionId?: IMediaSessionId) {
console.log('[KMC] handleRewind called')
return super.handleRewind(_sessionId)
}
async handleGetMetadataInfo(id: MediaId): Promise<IMediaMetadata> {
console.log('[KMC] handleGetMetadataInfo called', JSON.stringify(id))
return Promise.resolve({
mediaId: id.contentId,
title: 'Repro Title',
artwork: [],
})
}
async handleGetSessionState(sessionId?: IMediaSessionId) {
console.log('[KMC] handleGetSessionState called', JSON.stringify(sessionId))
return super.handleGetSessionState(sessionId)
}
}
App.tsx (player setup):
import React, { useEffect, useRef } from 'react'
import { View } from 'react-native'
import { VideoPlayer, KeplerVideoSurfaceView } from '@amazon-devices/react-native-w3cmedia'
import { useKeplerAppStateManager } from '@amazon-devices/react-native-kepler'
import { LoggingMediaControlHandler } from './LoggingMediaControlHandler'
export const App = () => {
const playerRef = useRef<VideoPlayer | null>(null)
const componentInstance = useKeplerAppStateManager().getComponentInstance()
useEffect(() => {
const player = new VideoPlayer()
playerRef.current = player
player
.setMediaControlFocus(componentInstance, new LoggingMediaControlHandler())
.then(() => player.initialize())
.then(() => {
// load any DASH/HLS media here, then player.play()
})
return () => { player.deinitialize() }
}, [componentInstance])
return (
<View style={{ flex: 1 }}>
<KeplerVideoSurfaceView
style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }}
onSurfaceViewCreated={(h) => playerRef.current?.setSurfaceHandle(h)}
onSurfaceViewDestroyed={(h) => playerRef.current?.clearSurfaceHandle(h)}
/>
</View>
)
}
package.json (relevant deps):
{
"dependencies": {
"@amazon-devices/kepler-media-controls": "~1.0.17",
"@amazon-devices/kepler-media-types": "~1.0.0",
"@amazon-devices/react-native-kepler": "^2.0.0",
"@amazon-devices/react-native-w3cmedia": "~2.1.87"
}
}
Playback Issues
This is not strictly a playback issue (playback itself works correctly via the W3C VideoPlayer), but for completeness:
- Player SDK:
@amazon-devices/react-native-w3cmediaVideoPlayer(W3C Media API) - Player SDK Version: 2.1.87
- Audio Codecs: AAC (mp4a.40.2)
- Video Codecs: H.264 (avc1)
- Manifest Types: DASH (.mpd)
The bug is reproducible regardless of the media URL — any video that the W3C player can play is sufficient to reproduce.
Additional Context
A closely related but less severe bug is already reported in this community:
- Alexa ‘Pause’ does not stop playback in Vega Media Controls (2026/04/21, by Kevin_Snijders)
- Reports that “Alexa pause” doesn’t stop playback in the Amazon official Vega Audio Sample App.
- Amazon’s response is “investigating” — unresolved for over a month at time of writing.
Our case appears to be on the same code path but more severe: not only Pause, but Play / Stop / TogglePlayPause / FastForward / Rewind are also silently dropped before reaching the JS handler.
Confirming that the issue reproduces on the official Vega Audio Sample App as reported in 28159 would strongly suggest this is a defect in the chromium-side W3C Media KMC integration native code, not anything specific to a particular app implementation.
Asks
- Please confirm whether the W3C Media KMC integration path is supposed to deliver transport control commands (Play/Pause/Stop/Toggle/FF/RW) to the JS-side
KeplerMediaControlHandleroverride, or whether they are intentionally handled entirely in chromium native. - If (1) is “handled in native,” what is the expected mechanism by which native pauses/resumes
MediaPlayerMPBImplwhen Alexa sends a Pause command?pauseInternal()is never called in our session. - If a fix is in progress, please share the target SDK release version / timeline.
Thanks!