mirror of
https://github.com/aykhans/AzSuicideDataVisualization.git
synced 2025-04-22 10:28:02 +00:00
247 lines
8.7 KiB
Python
247 lines
8.7 KiB
Python
# Copyright 2018-2022 Streamlit Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import io
|
|
import re
|
|
from typing import cast
|
|
|
|
from validators import url
|
|
|
|
import streamlit
|
|
from streamlit import type_util
|
|
from streamlit.in_memory_file_manager import in_memory_file_manager
|
|
from streamlit.proto.Audio_pb2 import Audio as AudioProto
|
|
from streamlit.proto.Video_pb2 import Video as VideoProto
|
|
|
|
|
|
class MediaMixin:
|
|
def audio(self, data, format="audio/wav", start_time=0):
|
|
"""Display an audio player.
|
|
|
|
Parameters
|
|
----------
|
|
data : str, bytes, BytesIO, numpy.ndarray, or file opened with
|
|
io.open().
|
|
Raw audio data, filename, or a URL pointing to the file to load.
|
|
Numpy arrays and raw data formats must include all necessary file
|
|
headers to match specified file format.
|
|
start_time: int
|
|
The time from which this element should start playing.
|
|
format : str
|
|
The mime type for the audio file. Defaults to 'audio/wav'.
|
|
See https://tools.ietf.org/html/rfc4281 for more info.
|
|
|
|
Example
|
|
-------
|
|
>>> audio_file = open('myaudio.ogg', 'rb')
|
|
>>> audio_bytes = audio_file.read()
|
|
>>>
|
|
>>> st.audio(audio_bytes, format='audio/ogg')
|
|
|
|
.. output::
|
|
https://share.streamlit.io/streamlit/docs/main/python/api-examples-source/charts.audio.py
|
|
height: 465px
|
|
|
|
"""
|
|
audio_proto = AudioProto()
|
|
coordinates = self.dg._get_delta_path_str()
|
|
marshall_audio(coordinates, audio_proto, data, format, start_time)
|
|
return self.dg._enqueue("audio", audio_proto)
|
|
|
|
def video(self, data, format="video/mp4", start_time=0):
|
|
"""Display a video player.
|
|
|
|
Parameters
|
|
----------
|
|
data : str, bytes, BytesIO, numpy.ndarray, or file opened with
|
|
io.open().
|
|
Raw video data, filename, or URL pointing to a video to load.
|
|
Includes support for YouTube URLs.
|
|
Numpy arrays and raw data formats must include all necessary file
|
|
headers to match specified file format.
|
|
format : str
|
|
The mime type for the video file. Defaults to 'video/mp4'.
|
|
See https://tools.ietf.org/html/rfc4281 for more info.
|
|
start_time: int
|
|
The time from which this element should start playing.
|
|
|
|
Example
|
|
-------
|
|
>>> video_file = open('myvideo.mp4', 'rb')
|
|
>>> video_bytes = video_file.read()
|
|
>>>
|
|
>>> st.video(video_bytes)
|
|
|
|
.. output::
|
|
https://share.streamlit.io/streamlit/docs/main/python/api-examples-source/charts.video.py
|
|
height: 700px
|
|
|
|
.. note::
|
|
Some videos may not display if they are encoded using MP4V (which is an export option in OpenCV), as this codec is
|
|
not widely supported by browsers. Converting your video to H.264 will allow the video to be displayed in Streamlit.
|
|
See this `StackOverflow post <https://stackoverflow.com/a/49535220/2394542>`_ or this
|
|
`Streamlit forum post <https://discuss.streamlit.io/t/st-video-doesnt-show-opencv-generated-mp4/3193/2>`_
|
|
for more information.
|
|
|
|
"""
|
|
video_proto = VideoProto()
|
|
coordinates = self.dg._get_delta_path_str()
|
|
marshall_video(coordinates, video_proto, data, format, start_time)
|
|
return self.dg._enqueue("video", video_proto)
|
|
|
|
@property
|
|
def dg(self) -> "streamlit.delta_generator.DeltaGenerator":
|
|
"""Get our DeltaGenerator."""
|
|
return cast("streamlit.delta_generator.DeltaGenerator", self)
|
|
|
|
|
|
# Regular expression explained at https://regexr.com/4n2l2 Covers any youtube
|
|
# URL (incl. shortlinks and embed links) and extracts its code.
|
|
YOUTUBE_RE = re.compile(
|
|
# Protocol
|
|
r"http(?:s?):\/\/"
|
|
# Domain
|
|
r"(?:www\.)?youtu(?:be\.com|\.be)\/"
|
|
# Path and query string
|
|
r"(?P<watch>(watch\?v=)|embed\/)?(?P<code>[\w\-\_]*)(&(amp;)?[\w\?=]*)?"
|
|
)
|
|
|
|
|
|
def _reshape_youtube_url(url):
|
|
"""Return whether URL is any kind of YouTube embed or watch link. If so,
|
|
reshape URL into an embed link suitable for use in an iframe.
|
|
|
|
If not a YouTube URL, return None.
|
|
|
|
Parameters
|
|
----------
|
|
url : str or bytes
|
|
|
|
Example
|
|
-------
|
|
>>> print(_reshape_youtube_url('https://youtu.be/_T8LGqJtuGc'))
|
|
|
|
.. output::
|
|
https://www.youtube.com/embed/_T8LGqJtuGc
|
|
"""
|
|
match = YOUTUBE_RE.match(url)
|
|
if match:
|
|
return "https://www.youtube.com/embed/{code}".format(**match.groupdict())
|
|
return None
|
|
|
|
|
|
def _marshall_av_media(coordinates, proto, data, mimetype):
|
|
"""Fill audio or video proto based on contents of data.
|
|
|
|
Given a string, check if it's a url; if so, send it out without modification.
|
|
Otherwise assume strings are filenames and let any OS errors raise.
|
|
|
|
Load data either from file or through bytes-processing methods into a
|
|
InMemoryFile object. Pack proto with generated Tornado-based URL.
|
|
"""
|
|
# Audio and Video methods have already checked if this is a URL by this point.
|
|
|
|
if isinstance(data, str):
|
|
# Assume it's a filename or blank. Allow OS-based file errors.
|
|
with open(data, "rb") as fh:
|
|
this_file = in_memory_file_manager.add(fh.read(), mimetype, coordinates)
|
|
proto.url = this_file.url
|
|
return
|
|
|
|
if data is None:
|
|
# Allow empty values so media players can be shown without media.
|
|
return
|
|
|
|
# Assume bytes; try methods until we run out.
|
|
if isinstance(data, bytes):
|
|
pass
|
|
elif isinstance(data, io.BytesIO):
|
|
data.seek(0)
|
|
data = data.getvalue()
|
|
elif isinstance(data, io.RawIOBase) or isinstance(data, io.BufferedReader):
|
|
data.seek(0)
|
|
data = data.read()
|
|
elif type_util.is_type(data, "numpy.ndarray"):
|
|
data = data.tobytes()
|
|
else:
|
|
raise RuntimeError("Invalid binary data format: %s" % type(data))
|
|
|
|
this_file = in_memory_file_manager.add(data, mimetype, coordinates)
|
|
proto.url = this_file.url
|
|
|
|
|
|
def marshall_video(coordinates, proto, data, mimetype="video/mp4", start_time=0):
|
|
"""Marshalls a video proto, using url processors as needed.
|
|
|
|
Parameters
|
|
----------
|
|
coordinates : str
|
|
proto : the proto to fill. Must have a string field called "data".
|
|
data : str, bytes, BytesIO, numpy.ndarray, or file opened with
|
|
io.open().
|
|
Raw video data or a string with a URL pointing to the video
|
|
to load. Includes support for YouTube URLs.
|
|
If passing the raw data, this must include headers and any other
|
|
bytes required in the actual file.
|
|
mimetype : str
|
|
The mime type for the video file. Defaults to 'video/mp4'.
|
|
See https://tools.ietf.org/html/rfc4281 for more info.
|
|
start_time : int
|
|
The time from which this element should start playing. (default: 0)
|
|
"""
|
|
|
|
proto.start_time = start_time
|
|
|
|
# "type" distinguishes between YouTube and non-YouTube links
|
|
proto.type = VideoProto.Type.NATIVE
|
|
|
|
if isinstance(data, str) and url(data):
|
|
youtube_url = _reshape_youtube_url(data)
|
|
if youtube_url:
|
|
proto.url = youtube_url
|
|
proto.type = VideoProto.Type.YOUTUBE_IFRAME
|
|
else:
|
|
proto.url = data
|
|
|
|
else:
|
|
_marshall_av_media(coordinates, proto, data, mimetype)
|
|
|
|
|
|
def marshall_audio(coordinates, proto, data, mimetype="audio/wav", start_time=0):
|
|
"""Marshalls an audio proto, using data and url processors as needed.
|
|
|
|
Parameters
|
|
----------
|
|
coordinates : str
|
|
proto : The proto to fill. Must have a string field called "url".
|
|
data : str, bytes, BytesIO, numpy.ndarray, or file opened with
|
|
io.open()
|
|
Raw audio data or a string with a URL pointing to the file to load.
|
|
If passing the raw data, this must include headers and any other bytes
|
|
required in the actual file.
|
|
mimetype : str
|
|
The mime type for the audio file. Defaults to "audio/wav".
|
|
See https://tools.ietf.org/html/rfc4281 for more info.
|
|
start_time : int
|
|
The time from which this element should start playing. (default: 0)
|
|
"""
|
|
|
|
proto.start_time = start_time
|
|
|
|
if isinstance(data, str) and url(data):
|
|
proto.url = data
|
|
|
|
else:
|
|
_marshall_av_media(coordinates, proto, data, mimetype)
|