Skip to content

Instantly share code, notes, and snippets.

@tvst
Last active May 8, 2021 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tvst/1e786a32fb93dd4ab3ebf46093c22f2e to your computer and use it in GitHub Desktop.
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)
#!/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