Audio.play() rejected with NotSupportedError inside Electron webview

Viewed 1247

I'm running an Electron (v2.0.3) project which executes scripts in a webview. One of the script is to play a local audio file under conditions.

However, the audio play is rejected if it's called inside a webview, while working fine if called in index.html or if an online audio file is played instead of a local one.

I've set nodeIntegration of the webview to true, and made sure the webview isn't muted. I guess it's not a problem about the auto-play policy because YouTube videos and online audio (e.g. http://www.pacdv.com/sounds/ambience_sounds/air_hum.wav) works perfectly if I load them in the webview.

Also, the file path and the file itself are no-problems, because it works good when I execute the script directly inside index.html.

Here's my index.html:

<head>
    <script>
        function init() {
            web.addEventListener("dom-ready", () => {
                web.executeJavaScript('<my-script>'); 
            }); 
        }
    </script>
</head>
<body onload="init(); ">
    <webview id="web" src="http://www.google.com" 
        style="width: 800px; height: 600px; "
        webpreferences="nodeIntegration=true"></webview>
</body>

Here's the content of <my-script>:

let path = `file://${require("electron").remote.app.getAppPath()}/xxx.mp3`; 
new Audio(path).play().then().catch(ex => {
    document.body.innerHTML = ex; 
}); 

After Audio.play(), the promise is rejected and show the error message:

NotSupportedError: Failed to load because no supported source was found.

I've once thought about the chance of cross-origin limitations, but it seems not because I can play online audio files from different domains like I stated before.

How can I fix this? Could this be a bug? Or do I forget about some restriction? Any information would be appreciated. Thanks.

Edit: According to my further test, this error also occurs when I call executeJavaScript() on the BrowserWindow.webContents created by main.js. So it seems like a limitation about executeJavaScript rather than the webview.

The docs have mentioned the userGesture limitation, which can be configured by the second parameter of executeJavaScript. However, it doesn't work for me, still.

1 Answers

add this line before the app start

app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required');
Related