Audio and Video Not Working in WebView

:backhand_index_pointing_right: Bug Description


1. Summary

On Amazon Fire TV, inside WebView, Video, HTML5 audio and Web Audio API playback do not work.
The playback call (video.play(), audio.play() or AudioContext.start()) resolves without throwing any error, but no sound or video is played.

App Name: N/A
App Link on Amazon Appstore: N/A

Bug Severity
Select one that applies

  • Impacts operation of app
  • Blocks current development
  • Improvement suggestion
  • Issue with documentation (If selected, please share the doc link and describe the issue)
  • Other

2. Steps to Reproduce

  1. Load a simple HTML page inside a WebView on Fire TV.
  2. Attempt to play any audio or video element.
  3. Observe the behavior when playback is triggered automatically or programmatically via JavaScript (audio.play() / video.play()).

3. Observed Behavior

  1. No audio or video is played.
  2. No errors or exceptions are thrown in the console.

4. Expected Behavior

  1. Audio and video should play.

4.a Possible Root Cause & Temporary Workaround

N/A

5. Logs or crash report

N/A

6. Environment

  • SDK Version: 0.21.4726

  • App State: Foreground

  • OS Information

    NAME="OS"
    OE_VERSION="4.0.0"
    OS_MAJOR_VERSION="1"
    OS_MINOR_VERSION="1"
    RELEASE_ID="10"
    OS_VERSION="1.1"
    BRANCH_CODE="TV Ship"
    BUILD_DESC="OS 1.1 (TV Ship/505)"
    BUILD_FINGERPRINT="4.0.173341.0(3072cab629675a74)/505N:user/release-keys"
    BUILD_VARIANT="user"
    BUILD_TAGS="release-keys"
    BUILD_DATE="Thu Oct 23 21:31:39 UTC 2025"
    BUILD_TIMESTAMP="1761255099"
    VERSION_NUMBER="1001010050520"
    

7. Example Code Snippet / Screenshots / Screengrabs

import * as React from 'react';
import {useRef} from 'react';
import {View, StyleSheet} from 'react-native';
import {WebView} from '@amazon-devices/webview';

export const App = () => {
  const webRef = useRef(null);
  return (
    <View style={styles.container}>
      <WebView
        ref={webRef}
        style={styles.webview}
        source={{uri: APP_URL}}
        allowSystemKeyEvents={true}
        allowsDefaultMediaControl={true}
        domStorageEnabled={true}
        javaScriptEnabled={true}
        hasTVPreferredFocus={true}
        mediaPlaybackRequiresUserAction={false}
        mixedContentMode="always"
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  webview: {
    backgroundColor: '#000000',
  },
});
[wants]

[[wants.service]]
id = "com.amazon.webview.renderer_service"

[[wants.service]]
id = "com.amazon.media.server"

[[wants.service]]
id = "com.amazon.audio.stream"
const a = new Audio('https://www.w3schools.com/html/horse.mp3');
try {
  await a.play();
  console.log('Audio started');
} catch (err) {
  console.error('Play error:', err);
}

:backhand_index_pointing_right: Additional Context


This is probably a similar issue to the one reported in this ticket: WebView video not playing on Fire TV Stick 4K Max (works on Android devices)

The video appears to pause immediately after starting and cannot be unpaused.

1 Like

Hi @8bitsten ,

Thank you for the detailed bug report on the WebView audio/video playback issue.

Our team is investigating this issue and will provide an update as soon as we have more information.

Thanks for helping us improve the Vega platform.

Warm regards,
Aishwarya

Hi @8bitsten,

Our team has investigated this issue and identified the root cause. The problem was due to missing permissions in app’s manifest file. We’ve tested the fix and can confirm that audio and video now work correctly in WebView on Fire TV.

Solution: Add Missing Services and Privileges

Please update your manifest.toml file to include these additional services and privileges:

[[wants.service]]
id = "com.amazon.mediametrics.service"  # Required for metrics service

[[wants.service]]
id = "com.amazon.gipc.uuid.*"

[[wants.service]]
id = "com.amazon.media.playersession.service"

[[wants.privilege]]
id = "com.amazon.devconf.privilege.accessibility"  # Required for captions

[[wants.service]]
id = "com.amazon.mediabuffer.service"

[[wants.service]]
id = "com.amazon.mediatransform.service"

[[wants.service]]
id = "com.amazon.audio.control"

[[wants.service]]
id = "com.amazon.audio.system"

Also add this to your [offers] section:

[offers]
[[offers.service]]
id = "com.amazon.gipc.uuid.*"

Next Steps:

  1. Update your manifest.toml with the above permissions
  2. Rebuild and test your app
  3. The audio and video playback should now work as expected

We’ve verified this fix resolves the issue where video.play() and audio.play() calls were resolving without errors but producing no output.

Thanks for helping us improve the Vega platform, and please let us know if you need any clarification on these changes.

Best regards,
Aishwarya

Hello @amen ,

Thank you for your quick response. Your solution helped partially, but not completely.

  1. The AudioContext doesn’t work at all. It behaves very strangely — when I try to play a sound using the AudioContext, nothing is heard. However, if I play a sound through an HTMLAudioElement, then both the Audio element and the AudioContext sounds start playing correctly. For example, if I let background music play through an Audio element and then play sounds through the AudioContext on top of it, they work fine. It also works temporarily if I start playback via an Audio element and then pause it — for a short time afterward, the AudioContext audio continues to work.

  2. The solution for Audio and Video elements works, but after some time (e.g. when playing multiple audio elements and then switching to video), both audio and video playback stop working — the video turns into a black screen and the sound stops completely. Only restarting the app helps. I can’t pinpoint exactly when this happens.
    Do you have any idea what might be causing this?

Best regards.

Hi @8bitsten ,

Thanks for the update! This AudioContext behavior is very interesting. To help debug this further, could you share:

  1. AudioContext code snippet - How you’re initializing and using AudioContext

  2. Audio element code - The working HTMLAudioElement implementation

  3. Sequence of events - Step-by-step what triggers the black screen/audio failure

  4. Memory/resource monitoring - Any console warnings about memory or resource limits

Thanks!

Hi @amen , I’ve encountered a similar issue (mentioned in Additional Context) on Amazon Fire TV when using React Native.

I originally posted it in the Fire Devices and App Store section, but haven’t received any replies yet. WebView video not playing on Fire TV Stick 4K Max (works on Android devices)

Since this thread discusses what looks like the same problem, could someone from the Amazon team please also review my report? It might help confirm whether the issue affects React Native on Fire OS as well.

Here’s the link to my post for reference: WebView video not playing on Fire TV Stick 4K Max (works on Android devices)

Thanks a lot for taking a look!

Hi @O_Karas ,

Thanks for checking in. The team is reviewing the issue and will provide updates on your original post so everything stays in one place. You can expect the follow-up there.

Thanks!

Hello @amen,

Sorry for the delayed response.

Here is a code snippet:

const html5Audio = new Audio('https://webaudioapi.com/samples/audio-tag/chrono.mp3');    
const context = new (window.AudioContext || window.webkitAudioContext)();
let audioContextSource = null;
let audioBuffer = null;

const initAudioContext = async () => {
    const response = await fetch('https://www.w3schools.com/html/horse.mp3');
    const arrayBuffer = await response.arrayBuffer();
    audioBuffer = await context.decodeAudioData(arrayBuffer);
    console.log('Web Audio initialized');
};

initAudioContext();

const playHtml5Audio = () => {
    html5Audio.play();
    console.log('HTML Audio play');
};
const stopHtml5Audio = () => {
    html5Audio.pause();
    html5Audio.currentTime = 0;
    console.log('HTML Audio stop');
};
const playAudioContext = () => {
    audioContextSource = context.createBufferSource();
    audioContextSource.buffer = audioBuffer;
    audioContextSource.connect(context.destination);
    audioContextSource.start(0);
    console.log('Audio Context play');
};
const stopAudioContext = async () => {
    if (audioContextSource) {
        audioContextSource.stop();
        audioContextSource = null;
        console.log('Audio Context stop');
    }
};

document.addEventListener('keydown', (event) => {
    if (event.key === 'ArrowUp') {
        playHtml5Audio();
    } else if (event.key === 'ArrowDown') {
        stopHtml5Audio();
    } else if (event.key === 'ArrowLeft') {
        playAudioContext();
    } else if (event.key === 'ArrowRight') {
        stopAudioContext();             
    }
});

The Audio Context sound will not play at all until I play HTML5 audio.

I am unable to determine the sequence of events leading to the black screen/audio failure. However, I did not notice any warnings regarding memory or resource limits.

Best Regards.

Hello @amen

Do you have any update on this?

Thank you in advance.

Hi @8bitsten,

Thank you for your patience while we investigate this issue. The team has reviewed your code and created a test page, identifying a potential issue with the audio URLs in your implementation - it appears the html5Audio and WebAudio URLs may need to be switched. The current setup is causing WebAudio playback to fail due to CORS policy blocking the fetch request.

Could you please:

  1. Confirm if the test page accurately represents your scenario

    <!DOCTYPE html>
    <html>
      <head>
        <style>
            body { font-family: Arial, sans-serif; padding: 20px; }
            .audio-control { margin: 20px 0; padding: 15px; border: 1px solid #ccc; border-radius: 5px; }
            .status { font-weight: bold; margin: 10px 0; }
            .playing { color: green; }
            .stopped { color: red; }
            .controls { margin: 10px 0; }
            button { margin: 5px; padding: 8px 15px; }
            .instructions { background: #f0f0f0; padding: 10px; margin: 20px 0; }
        </style>
        <script>
            const html5Audio = new Audio('https://webaudioapi.com/samples/audio-tag/chrono.mp3');    
            const context = new (window.AudioContext || window.webkitAudioContext)();
            let audioContextSource = null;
            let audioBuffer = null;
    
            const updateUI = () => {
                document.getElementById('html5Status').textContent = html5Audio.paused ? 'Stopped' : 'Playing';
                document.getElementById('html5Status').className = html5Audio.paused ? 'status stopped' : 'status playing';
                
                document.getElementById('contextStatus').textContent = audioContextSource ? 'Playing' : 'Stopped';
                document.getElementById('contextStatus').className = audioContextSource ? 'status playing' : 'status stopped';
            };
    
            const initAudioContext = async () => {
                const response = await fetch('https://www.w3schools.com/html/horse.mp3');
                const arrayBuffer = await response.arrayBuffer();
                audioBuffer = await context.decodeAudioData(arrayBuffer);
                console.log('Web Audio initialized');
            };
    
            initAudioContext();
    
            const playHtml5Audio = () => {
                html5Audio.play();
                console.log('HTML Audio play');
                updateUI();
            };
            const stopHtml5Audio = () => {
                html5Audio.pause();
                html5Audio.currentTime = 0;
                console.log('HTML Audio stop');
                updateUI();
            };
            const playAudioContext = () => {
                audioContextSource = context.createBufferSource();
                audioContextSource.buffer = audioBuffer;
                audioContextSource.connect(context.destination);
                audioContextSource.start(0);
                console.log('Audio Context play');
                updateUI();
            };
            const stopAudioContext = async () => {
                if (audioContextSource) {
                    audioContextSource.stop();
                    audioContextSource = null;
                    console.log('Audio Context stop');
                    updateUI();
                }
            };
    
            document.addEventListener('keydown', (event) => {
                if (event.key === 'ArrowUp') {
                    playHtml5Audio();
                } else if (event.key === 'ArrowDown') {
                    stopHtml5Audio();
                } else if (event.key === 'ArrowLeft') {
                    playAudioContext();
                } else if (event.key === 'ArrowRight') {
                    stopAudioContext();             
                }
            });
         </script>
      </head>
      <body>
        <h1>Audio Player Test</h1>
        
        <div class="audio-control">
            <h3>HTML5 Audio</h3>
            <div id="html5Status" class="status stopped">Stopped</div>
            <div class="controls">
                <button onclick="playHtml5Audio()">Play</button>
                <button onclick="stopHtml5Audio()">Stop</button>
            </div>
        </div>
    
        <div class="audio-control">
            <h3>Web Audio Context</h3>
            <div id="contextStatus" class="status stopped">Stopped</div>
            <div class="controls">
                <button onclick="playAudioContext()">Play</button>
                <button onclick="stopAudioContext()">Stop</button>
            </div>
        </div>
    
        <div class="instructions">
            <h4>Keyboard Controls:</h4>
            <p>↑ Arrow Up: Play HTML5 Audio</p>
            <p>↓ Arrow Down: Stop HTML5 Audio</p>
            <p>← Arrow Left: Play Web Audio Context</p>
            <p>→ Arrow Right: Stop Web Audio Context</p>
        </div>
      </body>
    </html>
    
  2. Check the console for any CORS errors or other warnings when the page loads and when you attempt playback

  3. Confirm whether the URLs in your actual implementation match those in your code snippet. If not, please share the details.

This will help the team better understand and resolve the issue you’re experiencing.

Best regards,
Aishwarya

Hello @amen

Thank you for your reply. Unfortunately, CORS is not the reason why it doesn’t work. I forgot to change the URL in the example. You can replace it with, for example: https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3

Here is a video showing the behavior: https://drive.google.com/file/d/1S_C_gdT3iLtZnqsY175qHCKP0t4aakdA/view

As you can see in the video, webAudio sound will not play until I start html5audo sound. At the same time, if I start webAudio sound and do not stop it, it will play simultaneously with html5audio sound.

Thank you in advance.