Video2gif / app.py
segestic's picture
Create app.py
55e7a66
import streamlit as st
import os
import base64
import tempfile
from PIL import Image
import numpy as np
from moviepy.editor import VideoFileClip
import moviepy.video.fx.all as vfx
## Session state ##
if 'clip_width' not in st.session_state:
st.session_state.clip_width = 0
if 'clip_height' not in st.session_state:
st.session_state.clip_height = 0
if 'clip_duration' not in st.session_state:
st.session_state.clip_duration = 0
if 'clip_fps' not in st.session_state:
st.session_state.clip_fps = 0
if 'clip_total_frames' not in st.session_state:
st.session_state.clip_total_frames = 0
st.title('🎈 Animated GIF Maker')
## Upload file ##
st.sidebar.header('Upload file')
uploaded_file = st.sidebar.file_uploader("Choose a file", type=['mov', 'mp4'])
st.sidebar.markdown('''
[Download example file](https://github.com/dataprofessor/animated-gif/raw/master/example/streamlit-app-starter-kit-screencast.mov)
---
Made with ❤️ by Chanin Nantasenamat ([Data Professor](https://youtube.com/dataprofessor))
''')
## Display gif generation parameters once file has been uploaded ##
if uploaded_file is not None:
## Save to temp file ##
tfile = tempfile.NamedTemporaryFile(delete=False)
tfile.write(uploaded_file.read())
## Open file ##
clip = VideoFileClip(tfile.name)
st.session_state.clip_duration = clip.duration
## Input widgets ##
st.sidebar.header('Input parameters')
selected_resolution_scaling = st.sidebar.slider('Scaling of video resolution', 0.0, 1.0, 0.5 )
selected_speedx = st.sidebar.slider('Playback speed', 0.1, 10.0, 5.0)
selected_export_range = st.sidebar.slider('Duration range to export', 0, int(st.session_state.clip_duration), (0, int(st.session_state.clip_duration) ))
## Resizing of video ##
clip = clip.resize(selected_resolution_scaling)
st.session_state.clip_width = clip.w
st.session_state.clip_height = clip.h
st.session_state.clip_duration = clip.duration
st.session_state.clip_total_frames = clip.duration * clip.fps
st.session_state.clip_fps = st.sidebar.slider('FPS', 10, 60, 20)
## Display output ##
st.subheader('Metrics')
col1, col2, col3, col4, col5 = st.columns(5)
col1.metric('Width', st.session_state.clip_width, 'pixels')
col2.metric('Height', st.session_state.clip_height, 'pixels')
col3.metric('Duration', st.session_state.clip_duration, 'seconds')
col4.metric('FPS', st.session_state.clip_fps, '')
col5.metric('Total Frames', st.session_state.clip_total_frames, 'frames')
# Extract video frame as a display image
st.subheader('Preview')
with st.expander('Show image'):
selected_frame = st.slider('Preview a time frame (s)', 0, int(st.session_state.clip_duration), int(np.median(st.session_state.clip_duration)) )
clip.save_frame('frame.gif', t=selected_frame)
frame_image = Image.open('frame.gif')
st.image(frame_image)
## Print image parameters ##
st.subheader('Image parameters')
with st.expander('Show image parameters'):
st.write(f'File name: `{uploaded_file.name}`')
st.write('Image size:', frame_image.size)
st.write('Video resolution scaling', selected_resolution_scaling)
st.write('Speed playback:', selected_speedx)
st.write('Export duration:', selected_export_range)
st.write('Frames per second (FPS):', st.session_state.clip_fps)
## Export animated GIF ##
st.subheader('Generate GIF')
generate_gif = st.button('Generate Animated GIF')
if generate_gif:
clip = clip.subclip(selected_export_range[0], selected_export_range[1]).speedx(selected_speedx)
frames = []
for frame in clip.iter_frames():
frames.append(np.array(frame))
image_list = []
for frame in frames:
im = Image.fromarray(frame)
image_list.append(im)
image_list[0].save('export.gif', format = 'GIF', save_all = True, loop = 0, append_images = image_list)
#clip.write_gif('export.gif', fps=st.session_state.clip_fps)
## Download ##
st.subheader('Download')
#video_file = open('export.gif', 'rb')
#video_bytes = video_file.read()
#st.video(video_bytes)
file_ = open('export.gif', 'rb')
contents = file_.read()
data_url = base64.b64encode(contents).decode("utf-8")
file_.close()
st.markdown(
f'<img src="data:image/gif;base64,{data_url}" alt="cat gif">',
unsafe_allow_html=True,
)
fsize = round(os.path.getsize('export.gif')/(1024*1024), 1)
st.info(f'File size of generated GIF: {fsize} MB', icon='💾')
fname = uploaded_file.name.split('.')[0]
with open('export.gif', 'rb') as file:
btn = st.download_button(
label='Download image',
data=file,
file_name=f'{fname}_scaling-{selected_resolution_scaling}_fps-{st.session_state.clip_fps}_speed-{selected_speedx}_duration-{selected_export_range[0]}-{selected_export_range[1]}.gif',
mime='image/gif'
)
## Default page ##
else:
st.warning('👈 Upload a video file')