St.video() issue - mp4 won't play on apple device

First a thank you to the streamlit team for an awesome app framework.

As part of a streamlit app that I’ve built I wanted to play a video of a matplotlib animation that I’d generated. Unfortunately the mp4 file wouldn’t play on an ipad and iphone (though it played fine on windows and android). I converted the mp4 to use h264; and I tried multiple ffmpeg flags to try and convert the mp4 to a format that would play but on ios but I wasn’t able to make it work.

I then set out to prove that the issue wasn’t with streamlit st.video() / apple. I downloaded the mp4 file that is used in the st.video() example in the streamlit API reference doc (Star - 6962.mp4) and built a simple app to display the file locally (from the app folder) and remotely (from an aws s3 folder).

I’ve deployed a simple test app that shows the issue on heroku: https://td-stvideo.herokuapp.com/.

I have found that I cannot play a local mp4 file using st.video() on an ipad (using safari, chrome and firefox) and on iphone (using safari) but I can play the same file remotely (located on a remote aws s3 folder) on ipad and iphone. I can play the file locally and remotely on my windows laptop and android phone, so the issue only applies to apple devices.

So why does st.video() work on ios with a remote file but not with a local file? Is there a problem with way st.video() - perhaps the underlying [html5?] video player - serves a local mp4 file on ios? Or are there known limtations that I’m not aware of? Or am I missing something in my code or analysis (see below)?

Has anyone managed to play a local mp4 file using st.video() on an ipad or iphone (using safari, chrome, or firefox)? My workaround is either use a gif (which plays ok on all devices that I’ve tested) or to upload the file to a remote platform (such as aws s3) and play from the video there.

Here is the simple code for that test app that demonstrates the issue (or my misunderstanding!).

import streamlit as st
LOCAL_MP4_FILE = "Star - 6962.mp4"
REMOTE_MP4_FILE = "https://td-public.s3-eu-west-1.amazonaws.com/Star+-+6962.mp4"

st.title("Demo st.video() issue")
st.write("Playing a local mp4 video file using st.video() is not working on apple devices")

choice = st.radio("Select mp4 file to display:", ('play local mp4 file', 'play remote mp4 file'))
if choice == 'play local mp4 file':
    # play local video
    st.write(f"st.video() with local file '{LOCAL_MP4_FILE}'")
    video_file = open(LOCAL_MP4_FILE, 'rb')
    video_bytes = video_file.read()
    st.video(video_bytes)
elif choice == 'play remote mp4 file':
    # play remote video
    st.write(f"st.video() with remote file '{REMOTE_MP4_FILE}'")
    st.video(REMOTE_MP4_FILE)

st.markdown("""Note: video is same as that used in streamlit API reference for st.video()  
Video credit:  
Creator: User fxxu from Pixabay  
URL: https://pixabay.com/en/videos/star-long-exposure-starry-sky-sky-6962/""")

When I select ‘play local mp4 file’ on ipad (safarai, chrome and firefox) and on iphone (safari) the video does not play e.g. with chrome on an ipad:


I’m using python 3.7.4 and streamlit 0.68.0. The test app is deployed on heroku-18.

1 Like

You are not alone, there’s been a few conversations about non-functioning media widgets and some components (like Ace Editor) on Safari Desktop and Safari/Chrome on iOS.

When I get a chance, I will modify the below bug request with your notes on the video editor as I’m certain these issues are related. (or you are more than welcome to comment to the bug with your notes)

My current theory is that mobile browsers on iOS have some kind of “feature” that requires some extra flavor in the HTML or JavaScript to prevent websites from running rogue or battery consuming scripts, audio, or video (but it’s not immediately obvious to my novice front end development knowledge). Safari for desktop is built heavily from a mobile mindset since Apple has been iOS first for a number of years so the same “feature” in iOS that is blocking this content ends up blocking in in MacOS as well.

https://github.com/streamlit/streamlit/issues/2139

1 Like

Thanks. I do find it strange that, for the 2 Apple devices that I tested with, playing a ‘remote’ file works but playing a ‘local’ file doesn’t. Given, I assume, that it’s the same video player that is serving both.

I thought it might have something to do with the remote file being fully qualified, so I gave the full path of the local file to st.video() - using os.path.abspath() - but unfortunately it didn’t make any difference.

A similar discussion happened here, I wonder if your issue gets solved as well:

1 Like

Thanks @randyzwitch, I updated the heroku demo app to use streamlit-nightly (0.68.2.dev20201012) and it now works! I tested on ipad (safari, chrome and firefox) and on iphone (safari).

1 Like