Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Autoplay mp4 video in WebView
-
For me, this works, after download of the MP4 as a local file
cover_image = ui.WebView() cover_image.load_url(os.path.abspath(local_file))
Sorry, perhaps I didn't read correctly your request, if so forget this reply
But, it plays automatically the MP4 and hides the commands after one second!
If you add
cover_image.touch_enabled = False
You can't stop the video
-
My objc_tools library has view's for AV players which can do autoplay
https://github.com/scj643/objc_tools/blob/master/objc_tools/ui/av.py
You would want to use a PlayerLayerView
-
@cvp Thanks for the suggestion! I didn't know that
ui.WebView()
can inherit the methods ofui.View()
. Now looks like there are a lot more things I can do withWebView
.I ended up adding a
button
so that the background video (without playback control) starts playing after clicking the "start game" button. This is done by usingeval_js()
in thebutton_tapped()
functionThe
html
template contains the followingvideo
tag:<video id="myvideo" preload="auto"> <source src="{{FPATH}}" type="video/mp4"> </video>
The Python code load
html
and useseval_js()
to start video play after clicking the button.v = ui.View() webview = ui.WebView() v.add_subview(webview) html = TEMPLATE.replace('{{FPATH}}', absfilepath) webview.load_html(html) def button_tapped(sender): webview.eval_js('document.getElementById("myvideo").play();') button = ui.Button(title="Start Game") button.action = button_tapped v.add_subview(button) v.frame = (0,0,500,500) webview.frame = (0,0,500,500) v.present()
So it looks like the user has to click on something to play any kind of video. Because simply calling
webview.eval_js('document.getElementById("myvideo").play();')
outside thebutton_tapped()
function does not make the video play. -
I wonder if you have tried a pause of some kind, to make sure the page and vieeo have loaded before trying the javascript?
I think in the past I have checked document.ready (I think) inside a while True/sleep loop. Since the user is not clickng on the webview, I dont think the webview knows the difference between a call from your button action, and a call from elsewhere. maybe (though i doubt it) you might need to run the command on the main thread, which could be the other difference.
-
@scj643 Thanks! I'll definitely install the library and try it out. I don't have experience using Objective-C, though.
-
@JonB I tried pause and other things to make sure the video is properly loaded. My conclusion is that the video has to be triggered by some kind of user input, either by the iOS playback controls or any kind of button click (a button in
html/js
or a button inui.Button()
witheval_js()
. I'm not exactly sure how the system prevents autoplay internally (maybe a older version of iOS Webkit), but now I've decided to go with a button trigger. -
My point is the webview doesn't know that a button in the ui was pushed. So this isnt some sort of security measure -- from the webviews perspective, it gets an evaljs that starts the video.
The code below worked for me. The view has to be presented, and maybe onscreen, already for this to work, which might be why it didnt work for you(if you called evaljs before present). The checking code i have was protective but might not be necessary. Also, I had to add a file://, but perhaps you already had that in your absfilepath.
One final note... if you simply load the video directly, no html,
webview.load_url(absfilepath)
the video is shown and played automatically, though you then have no control programatically i think.import ui import os,time # [~/Documents]$ wget http://techslides.com/demos/sample-videos/small.mp4 absfilepath=os.path.abspath('small.mp4') TEMPLATE=''' <video id="myvideo" autoplay preload="auto"> <source src="file://{{FPATH}}" type="video/mp4"> </video> ''' v = ui.View() webview = ui.WebView() v.add_subview(webview) html = TEMPLATE.replace('{{FPATH}}', absfilepath) webview.load_html(html) #button = ui.Button(title="Start Game") #button.action = button_tapped #v.add_subview(button) v.frame = (0,0,500,500) webview.frame = (0,0,500,500) v.present() #after view is presented, check that html is loaded, then play # might be better to check document.readyState, but sometimes this can be complete before you start id=webview.eval_js('document.getElementById("myvideo").id') while not id =='myvideo': print('sleeping') time.sleep(1) id=webview.eval_js('document.getElementById("myvideo").id') webview.eval_js('document.getElementById("myvideo").play();')
-
The view has to be presented, and maybe onscreen, already for this to work, which might be why it didnt work for you(if you called evaljs before present).
You are correct! Simply putting
webview.eval_js('document.getElementById("myvideo").play();')
afterv.present()
solved the problem -- Now it autoplays without any trigger.I did try
webview.load_url(absfilepath)
, and as you said, it does not give much programatical control.Thanks a lot for the help!
-
If you are on slack I can discuss my module in more detail.
-
@scj643 Thanks! I'll get a slack in case I need more help.
I thought I wouldn't have to use objc, but I just run into another problem that might need some objc: https://forum.omz-software.com/topic/3926/transparent-scene-background-using-objc_utils
-
Not sure what I’m doing wrong but this isn’t working for me
-
Do you have a gist or something of your code?