Search code examples
javascripthtmlwebviewjavafx-webengine

Silent YouTube Video Before It Plays


I created a very simple WebView Browser that will open a YouTube Video directly from some URL, say: https://www.youtube.com/watch?v=someId

All I want is to mute this video by default or before playing (i.e. once it's loaded).

What I tried is:

String muteScript = "window.onload = function() {\n" + 
                    "var videos = document.querySelectorAll('video'),\n" +
                    "audios = document.querySelectorAll('listen');\n" +
                    "[].forEach.call(videos, function(video) { video.muted = true; });\n" +
                    "[].forEach.call(audios, function(audio) { audio.muted = true; })}";

WebView browser = new WebView();
WebEngine webEngine = browser.getEngine();
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
        @Override
        public void changed(ObservableValue ov, Worker.State oS, Worker.State nS) {
               if (nS == Worker.State.SUCCEEDED) {
                   webEngine.executeScript(muteScript);
               }
        }});

The problem is, the video sound is playing a bit then stops.

Is there a way to mute it before it plays?


Update

I am still trying to find a working solution but it seems almost impossible. Somehow, even changing each video's attribute defaultMuted = true; does not have any effect.

It's worth mentioning that I could not by any mean mute the video unless it strictly plays a bit (back to square one!).. that's why my following workaround failed at the last step:

  1. Convert the YouTube URL to Embedded and set autoplay=0.
  2. Change all videos' muted attributes to true.
  3. Play the video by performing a click() on it pragmatically!

Result: No Effect.

Also I tried to trigger an event onwaiting at the beginning of the video to mute it after. But as I mentioned, muted = true; attribute seems to strictly mute the video while it's playing or at least played a bit even if it's paused.


Solution

  • I was attempting to hack the cookies of the WebView and find if I can make the Video muted similar to the other popular browsers when they remember the user's previous session preference.

    From there, I found out how to embed a YouTube Video with sound muted and that is by simply adding mute=1 to the video URL!!

    The approach is as follows:

    1. Get the Video URL.
    2. Convert it to Embedded.
    3. Add autoplay=1&mute=1 to the end of the URL.

    Done!

    String convertToEmbed(String url) {
        String pattern = "(?<=watch\\?v=|/videos/|embed\\/|youtu.be\\/|\\/v\\/|\\/e\\/|watch\\?v%3D|watch\\?feature=player_embedded&v=|%2Fvideos%2F|embed%\u200C\u200B2F|youtu.be%2F|%2Fv%2F)[^#\\&\\?\\n]*";
        Pattern compiledPattern = Pattern.compile(pattern);
        Matcher matcher = compiledPattern.matcher(url);
        if (matcher.find()) {
            return "https://www.youtube.com/embed/" + matcher.group() + "?autoplay=1&mute=1";
        }
        return null;
    }