Last active
May 8, 2021 21:06
-
-
Save tvst/1e786a32fb93dd4ab3ebf46093c22f2e to your computer and use it in GitHub Desktop.
Streamlit app that I use when compression video for the Streamlit website. (NOTE: Doesn't currently support audio)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import streamlit as st | |
import subprocess | |
import os | |
# Hack to make app runnable directly with "python scriptname.py" | |
if not st._is_running_with_streamlit: | |
import sys | |
import streamlit.bootstrap | |
st._is_running_with_streamlit = True | |
streamlit.bootstrap.run(__file__, "".join(sys.argv), sys.argv[1:], []) | |
sys.exit() | |
st.markdown(""" | |
# Compress video<br>from the comfort of your desktop | |
""", unsafe_allow_html=True) | |
try: | |
subprocess.Popen("ffmpeg", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) | |
except FileNotFoundError: | |
st.error( | |
""" | |
This app requires [ffmpeg](https://www.ffmpeg.org/download.html). | |
You can install it with: | |
* **Windows:** follow [these instructions](https://www.wikihow.com/Install-FFmpeg-on-Windows). | |
* **Mac:** install [Brew](https://brew.sh/), then run... | |
``` | |
brew install ffmpeg | |
``` | |
* **Debian/Ubuntu:** | |
``` | |
sudo apt install ffmpeg | |
``` | |
* **RedHat/Fedora:** | |
``` | |
dnf install ffmpeg | |
``` | |
""" | |
) | |
st.stop() | |
VIDEO_EXTENSIONS = [ | |
"avi", | |
"mov", | |
"mp4", | |
"mpeg", | |
"webm", | |
"m4v", | |
] | |
PRESETS = [ | |
"ultrafast", | |
"superfast", | |
"veryfast", | |
"faster", | |
"fast", | |
"medium", | |
"slow", | |
"slower", | |
"veryslow", | |
] | |
TUNINGS = [ | |
"", | |
"film", | |
"animation", | |
"grain", | |
"stillimage", | |
"fastdecode", | |
"zerolatency", | |
] | |
def cmd(*args): | |
result = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
for line in iter(lambda: result.stdout.readline(), b""): | |
st.text(line.decode("utf-8")) | |
run_compressor = False | |
file_names = [ | |
f for f in os.listdir(os.getcwd()) | |
if any(f.endswith(f'.{ext}') for ext in VIDEO_EXTENSIONS) | |
] | |
with st.form(key="videoform"): | |
input_filename = st.selectbox("Input filename", file_names) | |
output_filename = st.text_input("Output filename", "output.mp4") | |
preset = st.selectbox( | |
"Preset", PRESETS, 5, | |
help=""" | |
A preset is a collection of options that will provide a certain encoding speed to | |
compression ratio. A slower preset will provide better compression (compression is quality | |
per filesize). This means that, for example, if you target a certain file size or constant | |
bit rate, you will achieve better quality with a slower preset. Similarly, for constant | |
quality encoding, you will simply save bitrate by choosing a slower preset. | |
Use the slowest preset that you have patience for. | |
""" | |
) | |
tune = st.selectbox( | |
"Compression tuning", TUNINGS, | |
help=""" | |
You can change settings based upon the specifics of your input. Current tunings include: | |
* film – use for high quality movie content; lowers deblocking | |
* animation – good for cartoons; uses higher deblocking and more reference frames | |
* grain – preserves the grain structure in old, grainy film material | |
* stillimage – good for slideshow-like content | |
* fastdecode – allows faster decoding by disabling certain filters | |
* zerolatency – good for fast encoding and low-latency streaming | |
For example, if your input is animation then use the animation tuning, or if you want to | |
preserve grain in a film then use the grain tuning. | |
""" | |
) | |
two_passes = st.checkbox("Use two passes?", True, help="Slower but better") | |
faststart = st.checkbox( | |
"Fast start?", | |
True, | |
help="Moves the index to the beginning of the file.", | |
) | |
max_rate = st.number_input("Max bitrate (in MBs)", min_value=0.0, value=5.0) | |
video_rate = st.number_input("Target average video bitrate (in MBs)", min_value=0.0, value=0.5) | |
if st.form_submit_button("Run"): | |
run_compressor = True | |
if run_compressor: | |
command_line = [ | |
"ffmpeg", | |
"-i", input_filename, | |
"-c:v", "libx264" | |
] | |
if faststart: | |
command_line += ["-movflags", "+faststart"] | |
if preset: | |
command_line += ["-preset", preset] | |
if tune: | |
command_line += ["-tune", tune] | |
command_line += [ | |
"-maxrate", f"{max_rate}M", | |
"-b:v", f"{video_rate}M", | |
"-y", | |
] | |
with st.beta_expander("Logs"): | |
if two_passes: | |
cmd(*command_line, | |
"-pass", "1", | |
"-f", "mp4", "/dev/null" | |
) | |
# Second pass | |
cmd(*command_line, | |
"-pass", "2", | |
output_filename) | |
else: | |
cmd(*command_line, output_filename) | |
st.write(""" | |
# Done! | |
Output is below: | |
""") | |
st.video(output_filename) | |
st.balloons() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment