sam12345324 commited on
Commit
7b6adec
·
verified ·
1 Parent(s): 3147627

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -29
app.py CHANGED
@@ -25,21 +25,60 @@ def check_port(port):
25
  except socket.error:
26
  return False
27
 
28
- def merge_videos_and_audios(video_files, audio_files=None, orig_vol=1.0, music_vol=0.5):
29
  """
30
- Merge multiple video clips into one and optionally add a concatenated audio track.
31
- If audio_files is None, the video will retain its original audio (if any).
32
- Volumes for original video audio and background audio (if provided) can be controlled.
33
- Uses method='compose' to avoid cropping in landscape videos.
34
- Returns the path to the merged video file.
 
 
 
 
 
 
35
  """
36
  try:
37
- logger.info(f"Starting merge with {len(video_files)} video files and {len(audio_files) if audio_files else 0} audio files")
 
 
 
 
 
 
 
 
 
 
38
 
39
  # Create a temporary output path
40
  temp_dir = tempfile.mkdtemp()
41
- output_path = os.path.join(temp_dir, "merged_output.mp4")
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  # Load and concatenate video clips
44
  video_clips = [VideoFileClip(video) for video in video_files]
45
  final_video_clip = concatenate_videoclips(video_clips, method='compose')
@@ -48,7 +87,7 @@ def merge_videos_and_audios(video_files, audio_files=None, orig_vol=1.0, music_v
48
  video_duration = final_video_clip.duration or sum(clip.duration for clip in video_clips)
49
  logger.info(f"Total video duration: {video_duration} seconds")
50
 
51
- # Handle audio (optional)
52
  if audio_files:
53
  logger.info("Processing audio files")
54
  # Load and concatenate audio clips
@@ -94,10 +133,10 @@ def merge_videos_and_audios(video_files, audio_files=None, orig_vol=1.0, music_v
94
  clip.close()
95
  concatenated_audio.close()
96
 
97
- logger.info("Merge completed successfully")
98
  return output_path
99
  except Exception as e:
100
- error_msg = f"Error during video and audio merging: {str(e)}\n{traceback.format_exc()}"
101
  logger.error(error_msg)
102
  return error_msg
103
 
@@ -105,21 +144,16 @@ def merge_videos_and_audios(video_files, audio_files=None, orig_vol=1.0, music_v
105
 
106
  def gradio_merge_videos(video_files, audio_files, orig_vol, music_vol):
107
  """
108
- Gradio endpoint to merge videos and optionally add audio.
109
  Args:
110
- video_files: List of video file paths
111
  audio_files: List of audio file paths (optional)
112
  orig_vol: Volume for original video audio (0.0 to 1.0)
113
  music_vol: Volume for background audio (0.0 to 1.0)
114
  Returns:
115
- Path to the merged video file or error message
116
  """
117
- logger.info(f"Received {len(video_files)} video files and {len(audio_files) if audio_files else 0} audio files")
118
-
119
- if len(video_files) <= 1:
120
- error_msg = "Error: Please upload more than 1 video file."
121
- logger.error(error_msg)
122
- return error_msg
123
 
124
  result = merge_videos_and_audios(
125
  video_files, audio_files, orig_vol=orig_vol, music_vol=music_vol
@@ -127,10 +161,14 @@ def gradio_merge_videos(video_files, audio_files, orig_vol, music_vol):
127
 
128
  if isinstance(result, str) and result.startswith("Error"):
129
  logger.error(result)
130
- return result
131
  else:
132
  logger.info(f"Merge successful. Output saved at: {result}")
133
- return result # Gradio will serve this as a downloadable video
 
 
 
 
134
 
135
  # --- Main Execution ---
136
 
@@ -160,28 +198,28 @@ if __name__ == "__main__":
160
 
161
  with gr.Blocks(title="Video and Audio Merger API") as app:
162
  gr.Markdown("## Video and Audio Merger API")
163
- gr.Markdown("Upload more than 1 video file to merge them into a single video. Optionally upload audio files to add as background audio.")
164
 
165
  with gr.Row():
166
- video_input = gr.File(label="Video Files (more than 1)", type="filepath", file_count="multiple")
167
- audio_input = gr.File(label="Audio Files (Optional)", type="filepath", file_count="multiple")
168
 
169
  with gr.Row():
170
  orig_vol_input = gr.Slider(minimum=0.0, maximum=1.0, value=1.0, step=0.05, label="Original Video Audio Volume")
171
  music_vol_input = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="Background Audio Volume")
172
 
173
- output_video = gr.Video(label="Merged Video")
174
- merge_button = gr.Button("Merge Videos and Audios")
 
175
 
176
  merge_button.click(
177
  fn=gradio_merge_videos,
178
  inputs=[video_input, audio_input, orig_vol_input, music_vol_input],
179
- outputs=output_video
180
  )
181
 
182
  try:
183
  logger.info(f"Attempting to launch Gradio app on port {selected_port}")
184
- # Set share=True to bypass localhost check
185
  app.launch(server_port=selected_port, share=True)
186
  logger.info(f"Gradio app launched successfully on port {app.server_port}")
187
  except Exception as e:
 
25
  except socket.error:
26
  return False
27
 
28
+ def merge_videos_and_audios(video_files=None, audio_files=None, orig_vol=1.0, music_vol=0.5):
29
  """
30
+ Merge multiple video clips and/or audio clips based on inputs provided.
31
+ - If only video_files: Merge videos, retaining their original audio.
32
+ - If only audio_files: Merge audio files into a single audio file.
33
+ - If both: Merge videos and overlay the concatenated audio.
34
+ Args:
35
+ video_files: List of video file paths (optional)
36
+ audio_files: List of audio file paths (optional)
37
+ orig_vol: Volume for original video audio (0.0 to 1.0)
38
+ music_vol: Volume for background audio (0.0 to 1.0)
39
+ Returns:
40
+ Path to the merged file (video or audio) or error message.
41
  """
42
  try:
43
+ # Ensure at least two files are provided (videos, audios, or combination)
44
+ video_count = len(video_files) if video_files else 0
45
+ audio_count = len(audio_files) if audio_files else 0
46
+ total_files = video_count + audio_count
47
+
48
+ logger.info(f"Starting merge with {video_count} video files and {audio_count} audio files")
49
+
50
+ if total_files < 2:
51
+ error_msg = "Error: Please upload at least 2 files total (videos, audios, or a combination)."
52
+ logger.error(error_msg)
53
+ return error_msg
54
 
55
  # Create a temporary output path
56
  temp_dir = tempfile.mkdtemp()
 
57
 
58
+ # Case 1: Audio only
59
+ if audio_count >= 2 and video_count == 0:
60
+ output_path = os.path.join(temp_dir, "merged_output.mp3")
61
+ logger.info("Merging audio files only")
62
+
63
+ # Load and concatenate audio clips
64
+ audio_clips = [AudioFileClip(audio) for audio in audio_files]
65
+ final_audio_clip = concatenate_audioclips(audio_clips)
66
+
67
+ # Write the final audio
68
+ logger.info(f"Writing output audio to {output_path}")
69
+ final_audio_clip.write_audiofile(output_path, codec="mp3")
70
+
71
+ # Close resources
72
+ final_audio_clip.close()
73
+ for clip in audio_clips:
74
+ clip.close()
75
+
76
+ logger.info("Audio merge completed successfully")
77
+ return output_path
78
+
79
+ # Case 2: Video only or Video with Audio
80
+ output_path = os.path.join(temp_dir, "merged_output.mp4")
81
+
82
  # Load and concatenate video clips
83
  video_clips = [VideoFileClip(video) for video in video_files]
84
  final_video_clip = concatenate_videoclips(video_clips, method='compose')
 
87
  video_duration = final_video_clip.duration or sum(clip.duration for clip in video_clips)
88
  logger.info(f"Total video duration: {video_duration} seconds")
89
 
90
+ # Handle audio (if provided)
91
  if audio_files:
92
  logger.info("Processing audio files")
93
  # Load and concatenate audio clips
 
133
  clip.close()
134
  concatenated_audio.close()
135
 
136
+ logger.info("Video merge completed successfully")
137
  return output_path
138
  except Exception as e:
139
+ error_msg = f"Error during merging: {str(e)}\n{traceback.format_exc()}"
140
  logger.error(error_msg)
141
  return error_msg
142
 
 
144
 
145
  def gradio_merge_videos(video_files, audio_files, orig_vol, music_vol):
146
  """
147
+ Gradio endpoint to merge videos and/or audio.
148
  Args:
149
+ video_files: List of video file paths (optional)
150
  audio_files: List of audio file paths (optional)
151
  orig_vol: Volume for original video audio (0.0 to 1.0)
152
  music_vol: Volume for background audio (0.0 to 1.0)
153
  Returns:
154
+ Path to the merged file (video or audio) or error message
155
  """
156
+ logger.info(f"Received {len(video_files) if video_files else 0} video files and {len(audio_files) if audio_files else 0} audio files")
 
 
 
 
 
157
 
158
  result = merge_videos_and_audios(
159
  video_files, audio_files, orig_vol=orig_vol, music_vol=music_vol
 
161
 
162
  if isinstance(result, str) and result.startswith("Error"):
163
  logger.error(result)
164
+ return result, None
165
  else:
166
  logger.info(f"Merge successful. Output saved at: {result}")
167
+ # Return appropriate output based on file type
168
+ if result.endswith(".mp3"):
169
+ return None, result # Audio output
170
+ else:
171
+ return result, None # Video output
172
 
173
  # --- Main Execution ---
174
 
 
198
 
199
  with gr.Blocks(title="Video and Audio Merger API") as app:
200
  gr.Markdown("## Video and Audio Merger API")
201
+ gr.Markdown("Upload at least 2 files total (videos, audios, or a combination) to merge them. Videos and audios are optional.")
202
 
203
  with gr.Row():
204
+ video_input = gr.File(label="Video Files (Optional, at least 2 if no audio)", type="filepath", file_count="multiple")
205
+ audio_input = gr.File(label="Audio Files (Optional, at least 2 if no video)", type="filepath", file_count="multiple")
206
 
207
  with gr.Row():
208
  orig_vol_input = gr.Slider(minimum=0.0, maximum=1.0, value=1.0, step=0.05, label="Original Video Audio Volume")
209
  music_vol_input = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="Background Audio Volume")
210
 
211
+ output_video = gr.Video(label="Merged Video (if videos provided)")
212
+ output_audio = gr.Audio(label="Merged Audio (if only audios provided)")
213
+ merge_button = gr.Button("Merge Files")
214
 
215
  merge_button.click(
216
  fn=gradio_merge_videos,
217
  inputs=[video_input, audio_input, orig_vol_input, music_vol_input],
218
+ outputs=[output_video, output_audio]
219
  )
220
 
221
  try:
222
  logger.info(f"Attempting to launch Gradio app on port {selected_port}")
 
223
  app.launch(server_port=selected_port, share=True)
224
  logger.info(f"Gradio app launched successfully on port {app.server_port}")
225
  except Exception as e: