Pranjal Pruthi commited on
Commit
3921468
·
1 Parent(s): 687de06

Add application files and dependencies

Browse files
Files changed (2) hide show
  1. app.py +36 -20
  2. process_video.py +146 -49
app.py CHANGED
@@ -11,6 +11,9 @@ import uuid
11
  import shutil
12
  import re
13
  import time
 
 
 
14
 
15
 
16
  def check_dependencies():
@@ -182,12 +185,10 @@ def process_video(url):
182
  continue
183
 
184
  return trimmed_dir
185
-
186
  def main():
187
  st.title("⚡️ ISKM Spotify Service 🛎️")
188
  sac.alert(label='🪷🌹🪷Hare Krishna 🪷🌹🪷 | 🙌dandwat 🙇 pranam🙌 | 🙏please accept my humble obeisances | 🫡 🪷🌹All glories Srila Prabhupada🌹🪷🫡 | 🎵 Welcome to ISKM Spotify Service! 🎶 | 🎧 Enter a YouTube URL to transform it into divine format 🙏 ✅ v0.0.2 Nanda Gopa 👶🏻 Stage | 🚧 Maintaince Mode', size='xs', radius=55, color='orange', banner=sac.Banner(play=True, direction='right', speed=51, pauseOnHover=True), icon=True, closable=True)
189
 
190
-
191
  # Add instruction guide in an expander
192
  with st.expander("📚 Instructions"):
193
  st.markdown("""
@@ -218,35 +219,50 @@ def main():
218
  If you encounter any issues, please check the dependency status in the sidebar or contact support.
219
  """)
220
 
 
 
 
221
  url = st.text_input("Enter the YouTube URL:")
 
222
 
223
  if st.button("Process Video"):
224
  if url:
225
  with st.spinner("Processing video..."):
226
- result = process_video(url)
227
 
228
  if result:
229
- if os.path.isfile(result):
230
- st.success("Video processing completed!")
231
- st.download_button(
232
- label="Download Processed Video",
233
- data=open(result, 'rb'),
234
- file_name=os.path.basename(result),
235
- mime="video/mp4"
236
- )
237
- elif os.path.isdir(result):
238
- st.success("Playlist processing completed!")
239
- for video in glob.glob(f"{result}/*_f.mp4"):
 
 
 
 
240
  st.download_button(
241
- label=f"Download {os.path.basename(video)}",
242
- data=open(video, 'rb'),
243
- file_name=os.path.basename(video),
244
  mime="video/mp4"
245
  )
246
- else:
247
- st.error("An error occurred during processing.")
 
 
 
 
 
 
248
  else:
249
- st.warning("Please enter a YouTube URL.")
250
 
251
  if __name__ == "__main__":
 
252
  main()
 
11
  import shutil
12
  import re
13
  import time
14
+ import threading
15
+ job_statuses = {}
16
+
17
 
18
 
19
  def check_dependencies():
 
185
  continue
186
 
187
  return trimmed_dir
 
188
  def main():
189
  st.title("⚡️ ISKM Spotify Service 🛎️")
190
  sac.alert(label='🪷🌹🪷Hare Krishna 🪷🌹🪷 | 🙌dandwat 🙇 pranam🙌 | 🙏please accept my humble obeisances | 🫡 🪷🌹All glories Srila Prabhupada🌹🪷🫡 | 🎵 Welcome to ISKM Spotify Service! 🎶 | 🎧 Enter a YouTube URL to transform it into divine format 🙏 ✅ v0.0.2 Nanda Gopa 👶🏻 Stage | 🚧 Maintaince Mode', size='xs', radius=55, color='orange', banner=sac.Banner(play=True, direction='right', speed=51, pauseOnHover=True), icon=True, closable=True)
191
 
 
192
  # Add instruction guide in an expander
193
  with st.expander("📚 Instructions"):
194
  st.markdown("""
 
219
  If you encounter any issues, please check the dependency status in the sidebar or contact support.
220
  """)
221
 
222
+
223
+ # Your existing instruction guide code here
224
+
225
  url = st.text_input("Enter the YouTube URL:")
226
+ job_id = st.text_input("Enter Job ID (optional):")
227
 
228
  if st.button("Process Video"):
229
  if url:
230
  with st.spinner("Processing video..."):
231
+ result, error = process_video(url)
232
 
233
  if result:
234
+ st.success(f"Video processing completed! Job ID: {os.path.basename(os.path.dirname(result))}")
235
+ st.session_state['job_id'] = os.path.basename(os.path.dirname(result))
236
+ else:
237
+ st.error(f"An error occurred during processing: {error}")
238
+ else:
239
+ st.warning("Please enter a YouTube URL.")
240
+
241
+ if st.button("Check Job Status"):
242
+ if job_id:
243
+ status = get_job_status(job_id)
244
+ st.info(f"Job Status: {status}")
245
+ if status == "Completed":
246
+ result = get_job_result(job_id)
247
+ if result:
248
+ if os.path.isfile(result):
249
  st.download_button(
250
+ label="Download Processed Video",
251
+ data=open(result, 'rb'),
252
+ file_name=os.path.basename(result),
253
  mime="video/mp4"
254
  )
255
+ elif os.path.isdir(result):
256
+ for video in glob.glob(f"{result}/*_f.mp4"):
257
+ st.download_button(
258
+ label=f"Download {os.path.basename(video)}",
259
+ data=open(video, 'rb'),
260
+ file_name=os.path.basename(video),
261
+ mime="video/mp4"
262
+ )
263
  else:
264
+ st.warning("Please enter a Job ID.")
265
 
266
  if __name__ == "__main__":
267
+ check_dependencies()
268
  main()
process_video.py CHANGED
@@ -1,70 +1,167 @@
1
- import sys
2
- import json
3
  import os
4
- from datetime import datetime
5
  import subprocess
 
6
  import re
7
- import glob
 
 
 
 
 
8
 
9
- def run_command_with_progress(command, job_info, tool):
10
  process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
11
 
12
- while True:
13
- output = process.stdout.readline()
14
- if output == '' and process.poll() is not None:
15
- break
16
- if output:
17
- print(output.strip())
18
- update_job_status(job_info, f"{tool}: {output.strip()}")
19
 
20
- return process.poll()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
- def update_job_status(job_info, status):
23
- job_info["status"] = status
24
- with open(f"{job_info['output_dir']}/job_info.json", "w") as f:
25
- json.dump(job_info, f)
 
 
 
26
 
27
- def process_video(job_id, url):
28
- output_dir = f"./output_folder_{job_id}"
29
 
30
- with open(f"{output_dir}/job_info.json", "r") as f:
31
- job_info = json.load(f)
32
 
33
- update_job_status(job_info, "downloading")
 
 
 
34
 
 
 
 
 
 
 
 
 
 
 
 
35
  format = "bestvideo[height<=1080][ext=mp4]+bestaudio[ext=m4a]/best[height<=1080][ext=mp4]"
36
  download_command = f'yt-dlp --cookies cookies.txt -f "{format}" -N 64 -o "{output_dir}/%(title)s.%(ext)s" "{url}"'
37
 
38
- return_code = run_command_with_progress(download_command, job_info, "yt-dlp")
 
39
 
40
- if return_code != 0:
41
- update_job_status(job_info, "error: download failed")
42
- return
43
-
44
- video_file = glob.glob(f"{output_dir}/*.mp4")[0]
45
- trimmed_file = video_file.replace(".mp4", "_trimmed.mp4")
46
-
47
- update_job_status(job_info, "trimming")
48
- auto_editor_command = f'auto-editor "{video_file}" --margin 0.5sec --output "{trimmed_file}"'
49
- return_code = run_command_with_progress(auto_editor_command, job_info, "auto-editor")
50
 
51
  if return_code != 0:
52
- update_job_status(job_info, "error: trimming failed")
53
- return
54
 
55
- final_file = trimmed_file.replace("_trimmed.mp4", f"_f_{job_id}.mp4")
56
-
57
- update_job_status(job_info, "processing")
58
- ffmpeg_command = f'ffmpeg -y -i "{trimmed_file}" -map 0:v:0 -map 0:a:0 -c:v libx264 -preset ultrafast -crf 23 -maxrate 25M -vf "scale=-1:1080" -c:a aac -b:a 192k -ac 2 -strict -2 "{final_file}"'
59
- return_code = run_command_with_progress(ffmpeg_command, job_info, "ffmpeg")
60
-
61
- if return_code != 0:
62
- update_job_status(job_info, "error: final processing failed")
63
- return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
 
65
- update_job_status(job_info, "completed")
 
 
66
 
67
- if __name__ == "__main__":
68
- job_id = sys.argv[1]
69
- url = sys.argv[2]
70
- process_video(job_id, url)
 
 
 
1
  import os
2
+ import glob
3
  import subprocess
4
+ import uuid
5
  import re
6
+ import select
7
+ import shutil
8
+ import time
9
+ import streamlit as st
10
+
11
+
12
 
13
+ def run_command_with_progress(command, status_placeholder, progress_bar, tool_name, is_trimming=False):
14
  process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True)
15
 
16
+ status_placeholder.text(f"Using {tool_name}...")
17
+
18
+ output_lines = []
19
+ error_lines = []
20
+
21
+ duration = None
 
22
 
23
+ while True:
24
+ reads = [process.stdout.fileno(), process.stderr.fileno()]
25
+ ret = select.select(reads, [], [], 0.1)
26
+
27
+ for fd in ret[0]:
28
+ if fd == process.stdout.fileno():
29
+ read = process.stdout.readline()
30
+ if read:
31
+ output_lines.append(read.strip())
32
+ status_placeholder.text(f"{tool_name}: {read.strip()}")
33
+
34
+ if '[download]' in read:
35
+ match = re.search(r'(\d+\.\d+)%', read)
36
+ if match:
37
+ progress = min(float(match.group(1)), 100) / 100
38
+ progress_bar.progress(progress)
39
+
40
+ if fd == process.stderr.fileno():
41
+ read = process.stderr.readline()
42
+ if read:
43
+ error_lines.append(read.strip())
44
+
45
+ # Parse ffmpeg output
46
+ if tool_name == "ffmpeg":
47
+ duration_match = re.search(r'Duration: (\d{2}):(\d{2}):(\d{2}\.\d{2})', read)
48
+ if duration_match:
49
+ hours, minutes, seconds = map(float, duration_match.groups())
50
+ duration = hours * 3600 + minutes * 60 + seconds
51
 
52
+ time_match = re.search(r'time=(\d{2}):(\d{2}):(\d{2}\.\d{2})', read)
53
+ if time_match and duration:
54
+ hours, minutes, seconds = map(float, time_match.groups())
55
+ current_time = hours * 3600 + minutes * 60 + seconds
56
+ progress = min((current_time / duration), 1)
57
+ status_placeholder.text(f"{tool_name}: {progress*100:.2f}% complete")
58
+ progress_bar.progress(progress)
59
 
60
+ if process.poll() is not None:
61
+ break
62
 
63
+ return_code = process.poll()
 
64
 
65
+ if return_code != 0:
66
+ st.error(f"Error occurred during {tool_name} processing:")
67
+ for line in error_lines[-10:]: # Display last 10 error lines
68
+ st.error(line)
69
 
70
+ return return_code
71
+
72
+ def process_video(url, status_callback=None):
73
+ session_id = str(uuid.uuid4())
74
+ output_dir = f"./output_folder_{session_id}"
75
+ os.makedirs(output_dir, exist_ok=True)
76
+
77
+ for file in glob.glob(f"{output_dir}/*"):
78
+ os.remove(file)
79
+
80
+ content_type = "playlist" if "list=" in url else "video"
81
  format = "bestvideo[height<=1080][ext=mp4]+bestaudio[ext=m4a]/best[height<=1080][ext=mp4]"
82
  download_command = f'yt-dlp --cookies cookies.txt -f "{format}" -N 64 -o "{output_dir}/%(title)s.%(ext)s" "{url}"'
83
 
84
+ status_placeholder = st.empty() if status_callback is None else status_callback
85
+ progress_bar = st.progress(0)
86
 
87
+ return_code = run_command_with_progress(download_command, status_placeholder, progress_bar, "yt-dlp")
 
 
 
 
 
 
 
 
 
88
 
89
  if return_code != 0:
90
+ return None, "Error occurred during download."
 
91
 
92
+ if content_type == "video":
93
+ video_file = glob.glob(f"{output_dir}/*.mp4")[0]
94
+ trimmed_file = video_file.replace(".mp4", "_trimmed.mp4")
95
+
96
+ progress_bar.progress(0)
97
+ auto_editor_command = f'auto-editor "{video_file}" --margin 0.5sec --output "{trimmed_file}"'
98
+ return_code = run_command_with_progress(auto_editor_command, status_placeholder, progress_bar, "auto-editor", is_trimming=True)
99
+
100
+ if return_code != 0:
101
+ return None, "Error occurred during trimming."
102
+
103
+ final_file = trimmed_file.replace("_trimmed.mp4", f"_f_{session_id}.mp4")
104
+
105
+ progress_bar.progress(0)
106
+ ffmpeg_command = f'ffmpeg -y -i "{trimmed_file}" -map 0:v:0 -map 0:a:0 -c:v libx264 -preset ultrafast -crf 23 -maxrate 25M -vf "scale=-1:1080" -c:a aac -b:a 192k -ac 2 -strict -2 "{final_file}"'
107
+ return_code = run_command_with_progress(ffmpeg_command, status_placeholder, progress_bar, "ffmpeg")
108
+
109
+ if return_code != 0:
110
+ return None, "Error occurred during final processing."
111
+
112
+ return final_file, None
113
+
114
+ elif content_type == "playlist":
115
+ trimmed_dir = f"{output_dir}/trimmed"
116
+ os.makedirs(trimmed_dir, exist_ok=True)
117
+
118
+ for video_file in glob.glob(f"{output_dir}/*.mp4"):
119
+ video_name = os.path.basename(video_file).replace(".mp4", "")
120
+ trimmed_file = f"{trimmed_dir}/{video_name}_trimmed.mp4"
121
+
122
+ progress_bar.progress(0)
123
+ auto_editor_command = f'auto-editor "{video_file}" --margin 0.5sec --output "{trimmed_file}" --verbose'
124
+ return_code = run_command_with_progress(auto_editor_command, status_placeholder, progress_bar, "auto-editor", is_trimming=True)
125
+
126
+ if return_code != 0:
127
+ continue
128
+
129
+ final_file = f"{trimmed_dir}/{video_name}_f.mp4"
130
+
131
+ progress_bar.progress(0)
132
+ ffmpeg_command = f'ffmpeg -y -i "{trimmed_file}" -map 0:v:0 -map 0:a:0 -c:v libx264 -preset ultrafast -crf 23 -maxrate 25M -vf "scale=-1:1080" -c:a aac -b:a 192k -ac 2 -strict -2 "{final_file}"'
133
+ return_code = run_command_with_progress(ffmpeg_command, status_placeholder, progress_bar, "ffmpeg")
134
+
135
+ if return_code != 0:
136
+ continue
137
+
138
+ return trimmed_dir, None
139
+
140
+ def get_job_status(session_id):
141
+ output_dir = f"./output_folder_{session_id}"
142
+ if not os.path.exists(output_dir):
143
+ return "Job not found"
144
+
145
+ if glob.glob(f"{output_dir}/*_f_{session_id}.mp4"):
146
+ return "Completed"
147
+ elif glob.glob(f"{output_dir}/trimmed/*_f.mp4"):
148
+ return "Completed"
149
+ elif glob.glob(f"{output_dir}/*.mp4"):
150
+ return "Processing"
151
+ else:
152
+ return "Downloading"
153
+
154
+ def get_job_result(session_id):
155
+ output_dir = f"./output_folder_{session_id}"
156
+ if not os.path.exists(output_dir):
157
+ return None
158
+
159
+ single_video = glob.glob(f"{output_dir}/*_f_{session_id}.mp4")
160
+ if single_video:
161
+ return single_video[0]
162
 
163
+ playlist_dir = f"{output_dir}/trimmed"
164
+ if os.path.exists(playlist_dir):
165
+ return playlist_dir
166
 
167
+ return None