Android Question How to unmute the sound in a HTML5 TV streams player

Syd Wright

Well-Known Member
Licensed User
In recent months almost half of all local Dutch TV stations have switched to HTML5 to stream their programs. I have managed to get a HTML5 TV player working on the basis of:
The only problem is that the sound of nearly all stations is muted once the player starts. The user has to press the loudspeaker button to listen to the sound.
I have temporarily solved it by simulating two mouse clicks (using gesturedetector): the first click is to make the controls appear and the second is to click on the loudspeaker button. It works, but is rather clumsey and probably won't work on screens with different aspect ratio.

Can someone please make a javascript that automatically clicks on the loudspeaker button once the webview pagefinished event has fired? In the html source the code "mute=muted" then disappears. Here is my code:
HTML5 TV player:
Sub Process_Globals
    Dim GestDet1 As GestureDetector
End Sub

Sub Globals
    Dim Webview1 As WebView
    Dim WebviewExtras1 As WebViewExtras
    Dim WebViewSettings1 As WebViewSettings
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Webview1.Initialize("Webview1")
    WebviewExtras1.addWebChromeClient(Webview1,"WebviewExtras1")
'    WebViewSettings1.setAllowFileAccess(Webview1,True)                 'Not needed!
'    WebViewSettings1.setAppCacheEnabled(Webview1,True)                 'Not needed!
    WebViewSettings1.setDOMStorageEnabled(Webview1,True)                'Needed!

    Activity.AddView(Webview1,0,5%y,100%x,100%y)                        'All these streams work, but are muted:
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/f80cee88_0D171E")    'RTV Purmerend
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/fc53f324_0D171E")    'RTV Krimpenerwaard
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/88729a5a_0D171E")    'Schie TV
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/478ebcbd_0D171E")    'RTV Bodegraven
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/387cc0bd_0D171E")    'RTV Meppel
    Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/0d8a1afd_0D171E")     'RTV IJsselmond
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Webview1_PageFinished (Url As String) 'Event
    Log("Webview1 Page Finished")

    Sleep(250)
    Dim MEv As Object = GestDet1.CreateMotionEvent(DateTime.Now,DateTime.Now,GestDet1.ACTION_DOWN,50%x,50%y)     'Simulate click event to show the player controls
    GestDet1.PassTouchEventTo(MEv, Webview1)
    Dim MEv As Object = GestDet1.CreateMotionEvent(DateTime.Now,DateTime.Now,GestDet1.ACTION_UP,50%x,50%y)
    GestDet1.PassTouchEventTo(MEv, Webview1)

    Sleep(500)
    Dim MEv As Object = GestDet1.CreateMotionEvent(DateTime.Now,DateTime.Now,GestDet1.ACTION_DOWN,18.3%x,91.1%y)  'Simulate click event to start playing (unmute)!
    GestDet1.PassTouchEventTo(MEv, Webview1)
    Dim MEv As Object = GestDet1.CreateMotionEvent(DateTime.Now,DateTime.Now,GestDet1.ACTION_UP,18.3%x,91.1%y)
    GestDet1.PassTouchEventTo(MEv, Webview1)
    Return

    Dim Javascript As String            'Experiment, does not work
    Javascript = "document.getElementById('player1594582608592_empHLS-MSE_api').setAttribute('muted','unmuted'); "
    WebviewExtras1.ExecuteJavascript(Webview1,Javascript)
End Sub
 
Last edited:

JohnC

Expert
Licensed User
Those gestures are triggering events somewhere in the page's html code.

My only suggestion is to find out the names of the events that those gestures are triggering and then do "ExecuteJavascript" to execute those events directly without sending any gestures.

(The event subs for the player are probably located in an external javascript file that is "included" into the webpage from an external source)
 
Upvote 0

Syd Wright

Well-Known Member
Licensed User
Thank you, but I already knew that. Also, as you can see, tip-1 is already satisfied in the code and tip-2 is for novices. If you look at my code you can see that I am already experimenting with Javascripts. The gestures are a temporary solution (which does however work).
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
When you look into the source for the URL (https://wl-0d171e.enigmatv.io/play/anonymous/0d8a1afd_0D171E), you can see two mentioned javascript includes:

B4X:
 <script src="https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/3.2.0/adyen.js"></script>
<script type="text/javascript" src="/app-7e0a2510583ed49b1c49.js?7e0a2510583ed49b1c49"></script>

So did you downloaded each of those .js files (as well as any additional .js files referenced in them, and so on) and search for any direct events related to starting the video that can be called directly (instead of indirectly with the gesture events)?
 
Upvote 0

Syd Wright

Well-Known Member
Licensed User
Script-1 has to do with payments or subscriptions (related to the Adyen pay portal). The second I don't yet know. I was not expecting the solution to my problem to be hidden inside a script. I'm also wondering why you keep adding these two "B4A Top New User Tips". I thought you put them there to help solve my problem... Rather confusing.
 
Upvote 0

JohnC

Expert
Licensed User
The "B4A TOP NEW USER TIPS:" are just solutions to two common problems new B4A users run into: 1) Webview not working right, or 2) App doesn't run or replaces another app when deployed.

Since they are usually not related to a post I am making, that's why they are in the signature section (grey text color section) of my post and not in the main body of my post.

For example, other users will include links to their libraries in their signature even though they may have nothing to do with their post.

Sorry for the confusion.
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
I was not expecting the solution to my problem to be hidden inside a script.

Keep in mind that many .js files are minified or obfuscated to make then compact and/or hard to reverse engineer.

But somewhere in the right .js file is the gesture event handler for the video player. And hopefully you will be able to see what variable gets changed or what routine gets called when the gesture routine determines that the user clicked on the mute button.

Once you know this, then you can inject and execute javascript code to change that variable value or call the sub that toggles the audio so you can control it directly regardless of the screen size or orientation.
 
Upvote 0

JohnC

Expert
Licensed User
...Another thought is that you may be able to use a desktop browser in debug mode and obtain the ID/name of the mute button, then send a click gesture to the button name/id directly to toggle it.
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
I tried loading in those enigmatv.io urls to try to help you find the mute button id, but all that appears in my firefox browser is 3 red dots jumping around in the center and a cookie button that I can not click "OK" because it's dimmed.
 
Upvote 0

Syd Wright

Well-Known Member
Licensed User
Thank you for trying to help me. The three red dots disappear after a few seconds and the TV stream starts to play. All Dutch stations seem to use the same HTML5 player.
Use this stream: https://wl-0d171e.enigmatv.io/play/anonymous/0d8a1afd_0D171E

In Firefox right click and select "Element inspect". Under the Inspector tab you will see a line like this:

<video id="player1594676978309_empShaka_api" class="vjs-tech" playsinline="playsinline" autoplay="" src="blob:https://wl-0d171e.enigmatv.io/0049b2fc-e6d0-4c8d-bf37-439a7632e5d7" muted="muted"></video>

When clicking on the loudspeaker button the text 'muted="muted"' can be toggled: either it is there or not. That's the only clue I have.

PS: It also works in chrome. Click on the link above, right click and then select 'Inspector"
PPS: Maybe the TV streams are blocked outside of The Netherlands.
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
Try this:
B4X:
Dim Javascript As String
Javascript = "document.getElementById('player1594582608592_empHLS-MSE_api').muted = false;"
WebviewExtras1.ExecuteJavascript(Webview1,Javascript)

And if that doesn't work, try substituting this line:
B4X:
Javascript = "var video = document.getElementById('player1594582608592_empHLS-MSE_api'); video.muted = false;"
 
Upvote 0

Syd Wright

Well-Known Member
Licensed User
Thank you very much. I tried both scripts but sadly they don't work. The problem is also that the player-id changes every time! So I made code to determine the player-id before executing your Javascript. Here is the entire code:
HTML5 TV player, Experiment-2:
Sub Process_Globals
    Dim GestDet1 As GestureDetector
End Sub

Sub Globals
    Dim Webview1 As WebView
    Dim WebviewExtras1 As WebViewExtras
    Dim WebViewSettings1 As WebViewSettings
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Webview1.Initialize("Webview1")
    WebviewExtras1.addWebChromeClient(Webview1,"WebviewExtras1")
    WebViewSettings1.setDOMStorageEnabled(Webview1,True)            'Needed!
    WebviewExtras1.addJavascriptInterface(Webview1, "B4A")

    Activity.AddView(Webview1,0,5%y,100%x,100%y)
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/f80cee88_0D171E")    'RTV Purmerend
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/fc53f324_0D171E")    'RTV Krimpenerwaard
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/88729a5a_0D171E")    'Schie TV
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/478ebcbd_0D171E")    'RTV Bodegraven
    'Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/387cc0bd_0D171E")    'RTV Meppel
    Webview1.LoadUrl("https://wl-0d171e.enigmatv.io/play/anonymous/0d8a1afd_0D171E")     'RTV IJsselmond
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub Webview1_PageFinished (Url As String) 'Event
    Dim Javascript As String
    Log("Webview1 Page Finished")

    Javascript = "B4A.CallSub('HTML_Test1', true, document.activeElement.innerHTML)"
    WebviewExtras1.executeJavascript(Webview1, Javascript)
End Sub

Sub HTML_Test1(HTML As String)
    Dim n As Long
    Dim Player1 As String
    n=HTML.IndexOf("_api")+4
    If n>50 Then
      Player1=HTML.SubString2(n-50,n)
      n=Player1.IndexOf2("player",0)
      If n=-1 Then Return
      Player1 = Player1.SubString2(n,Player1.Length)
    End If
    Log("Player1= " & Player1)            'This correctly gets the playerid.

    Dim Javascript As String
    'Javascript = "var video = document.getElementById('" & Player1 & "'); video.muted = false;"
    'Javascript = "var video = document.getElementById('" & Player1 & "'); video.muted = " & Chr(34) & Chr(34) & ";"
    'Javascript = "document.getElementById('" & Player1 & "').muted = ;"
    'Javascript = "document.getElementById('" & Player1 & "').muted=" & Chr(34) & Chr(34) & ";"
    'Javascript = "document.getElementById('" & Player1 & "').muted=!muted;"
    'Javascript = "document.getElementById('" & Player1 & "').volume = 1;"
    'Javascript = "var video = document.getElementById('" & Player1 & "'); video.volume = 1;"
    Javascript = "document.getElementById('" & Player1 & "').muted = false;"
    WebviewExtras1.ExecuteJavascript(Webview1,Javascript)

    'Msgbox(HTML,"")
End Sub
 
Last edited:
Upvote 0

JohnC

Expert
Licensed User
According to this page, that should have worked:
 
Upvote 0

Syd Wright

Well-Known Member
Licensed User
Thank you again for your help. I tried all sorts of javascripts (based on your information), but they all failed. So I will now have to wave the white flag.
I guess I'll have to stick to the gesture detector click-events solution (unless someone comes up with a better solution).
 
Upvote 0
Top