segestic commited on
Commit
55e7a66
1 Parent(s): 5bfa737

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +139 -0
app.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ import base64
4
+ import tempfile
5
+ from PIL import Image
6
+ import numpy as np
7
+ from moviepy.editor import VideoFileClip
8
+ import moviepy.video.fx.all as vfx
9
+
10
+ ## Session state ##
11
+ if 'clip_width' not in st.session_state:
12
+ st.session_state.clip_width = 0
13
+ if 'clip_height' not in st.session_state:
14
+ st.session_state.clip_height = 0
15
+ if 'clip_duration' not in st.session_state:
16
+ st.session_state.clip_duration = 0
17
+ if 'clip_fps' not in st.session_state:
18
+ st.session_state.clip_fps = 0
19
+ if 'clip_total_frames' not in st.session_state:
20
+ st.session_state.clip_total_frames = 0
21
+
22
+ st.title('🎈 Animated GIF Maker')
23
+
24
+ ## Upload file ##
25
+ st.sidebar.header('Upload file')
26
+ uploaded_file = st.sidebar.file_uploader("Choose a file", type=['mov', 'mp4'])
27
+ st.sidebar.markdown('''
28
+ [Download example file](https://github.com/dataprofessor/animated-gif/raw/master/example/streamlit-app-starter-kit-screencast.mov)
29
+
30
+ ---
31
+ Made with ❤️ by Chanin Nantasenamat ([Data Professor](https://youtube.com/dataprofessor))
32
+ ''')
33
+
34
+ ## Display gif generation parameters once file has been uploaded ##
35
+ if uploaded_file is not None:
36
+ ## Save to temp file ##
37
+ tfile = tempfile.NamedTemporaryFile(delete=False)
38
+ tfile.write(uploaded_file.read())
39
+
40
+ ## Open file ##
41
+ clip = VideoFileClip(tfile.name)
42
+
43
+ st.session_state.clip_duration = clip.duration
44
+
45
+ ## Input widgets ##
46
+ st.sidebar.header('Input parameters')
47
+ selected_resolution_scaling = st.sidebar.slider('Scaling of video resolution', 0.0, 1.0, 0.5 )
48
+ selected_speedx = st.sidebar.slider('Playback speed', 0.1, 10.0, 5.0)
49
+ selected_export_range = st.sidebar.slider('Duration range to export', 0, int(st.session_state.clip_duration), (0, int(st.session_state.clip_duration) ))
50
+
51
+ ## Resizing of video ##
52
+ clip = clip.resize(selected_resolution_scaling)
53
+
54
+ st.session_state.clip_width = clip.w
55
+ st.session_state.clip_height = clip.h
56
+ st.session_state.clip_duration = clip.duration
57
+ st.session_state.clip_total_frames = clip.duration * clip.fps
58
+ st.session_state.clip_fps = st.sidebar.slider('FPS', 10, 60, 20)
59
+
60
+ ## Display output ##
61
+ st.subheader('Metrics')
62
+ col1, col2, col3, col4, col5 = st.columns(5)
63
+ col1.metric('Width', st.session_state.clip_width, 'pixels')
64
+ col2.metric('Height', st.session_state.clip_height, 'pixels')
65
+ col3.metric('Duration', st.session_state.clip_duration, 'seconds')
66
+ col4.metric('FPS', st.session_state.clip_fps, '')
67
+ col5.metric('Total Frames', st.session_state.clip_total_frames, 'frames')
68
+
69
+ # Extract video frame as a display image
70
+ st.subheader('Preview')
71
+
72
+ with st.expander('Show image'):
73
+ selected_frame = st.slider('Preview a time frame (s)', 0, int(st.session_state.clip_duration), int(np.median(st.session_state.clip_duration)) )
74
+ clip.save_frame('frame.gif', t=selected_frame)
75
+ frame_image = Image.open('frame.gif')
76
+ st.image(frame_image)
77
+
78
+ ## Print image parameters ##
79
+ st.subheader('Image parameters')
80
+ with st.expander('Show image parameters'):
81
+ st.write(f'File name: `{uploaded_file.name}`')
82
+ st.write('Image size:', frame_image.size)
83
+ st.write('Video resolution scaling', selected_resolution_scaling)
84
+ st.write('Speed playback:', selected_speedx)
85
+ st.write('Export duration:', selected_export_range)
86
+ st.write('Frames per second (FPS):', st.session_state.clip_fps)
87
+
88
+ ## Export animated GIF ##
89
+ st.subheader('Generate GIF')
90
+ generate_gif = st.button('Generate Animated GIF')
91
+
92
+ if generate_gif:
93
+ clip = clip.subclip(selected_export_range[0], selected_export_range[1]).speedx(selected_speedx)
94
+
95
+ frames = []
96
+ for frame in clip.iter_frames():
97
+ frames.append(np.array(frame))
98
+
99
+ image_list = []
100
+
101
+ for frame in frames:
102
+ im = Image.fromarray(frame)
103
+ image_list.append(im)
104
+
105
+ image_list[0].save('export.gif', format = 'GIF', save_all = True, loop = 0, append_images = image_list)
106
+
107
+ #clip.write_gif('export.gif', fps=st.session_state.clip_fps)
108
+
109
+ ## Download ##
110
+ st.subheader('Download')
111
+
112
+ #video_file = open('export.gif', 'rb')
113
+ #video_bytes = video_file.read()
114
+ #st.video(video_bytes)
115
+
116
+ file_ = open('export.gif', 'rb')
117
+ contents = file_.read()
118
+ data_url = base64.b64encode(contents).decode("utf-8")
119
+ file_.close()
120
+ st.markdown(
121
+ f'<img src="data:image/gif;base64,{data_url}" alt="cat gif">',
122
+ unsafe_allow_html=True,
123
+ )
124
+
125
+ fsize = round(os.path.getsize('export.gif')/(1024*1024), 1)
126
+ st.info(f'File size of generated GIF: {fsize} MB', icon='💾')
127
+
128
+ fname = uploaded_file.name.split('.')[0]
129
+ with open('export.gif', 'rb') as file:
130
+ btn = st.download_button(
131
+ label='Download image',
132
+ data=file,
133
+ 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',
134
+ mime='image/gif'
135
+ )
136
+
137
+ ## Default page ##
138
+ else:
139
+ st.warning('👈 Upload a video file')