File size: 5,036 Bytes
55e7a66 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
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')
|