sampleacc-3003 commited on
Commit
a7f2779
Β·
verified Β·
1 Parent(s): 1df1cae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -144
app.py CHANGED
@@ -9,162 +9,162 @@ from datetime import datetime
9
  static_ffmpeg.add_paths()
10
 
11
  def stitch_media(video_file, audio_file, subtitle_file, crf_quality=23):
12
- """
13
- Stitch video, audio, and subtitle files together using ffmpeg
14
- All files are handled through Gradio's temporary file system
15
- """
16
- try:
17
- # Validate inputs
18
- if not video_file or not audio_file or not subtitle_file:
19
- return None, "❌ Please upload all three files (video, audio, subtitle)"
20
-
21
- # Gradio automatically provides temporary file paths
22
- video_path = video_file.name if hasattr(video_file, 'name') else video_file
23
- audio_path = audio_file.name if hasattr(audio_file, 'name') else audio_file
24
- subtitle_path = subtitle_file.name if hasattr(subtitle_file, 'name') else subtitle_file
25
-
26
- # Create output file in temp directory
27
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
28
- output_path = os.path.join(tempfile.gettempdir(), f"stitched_{timestamp}.mp4")
29
-
30
- # FFmpeg command
31
- cmd = [
32
- "ffmpeg",
33
- "-i", video_path,
34
- "-i", audio_path,
35
- "-vf", f"subtitles={subtitle_path}",
36
- "-map", "0:v",
37
- "-map", "1:a",
38
- "-c:v", "libx264",
39
- "-crf", str(crf_quality),
40
- "-c:a", "aac",
41
- "-y",
42
- output_path
43
- ]
44
-
45
- # Execute ffmpeg
46
- process = subprocess.run(
47
- cmd,
48
- check=True,
49
- capture_output=True,
50
- text=True
51
- )
52
-
53
- # Check if output file was created
54
- if os.path.exists(output_path):
55
- file_size = os.path.getsize(output_path) / (1024 * 1024) # Size in MB
56
- return output_path, f"βœ… Video stitched successfully! (Size: {file_size:.2f} MB)"
57
- else:
58
- return None, "❌ Output file was not created"
59
-
60
- except subprocess.CalledProcessError as e:
61
- error_msg = f"❌ FFmpeg error:\n{e.stderr[-500:]}" # Show last 500 chars of error
62
- return None, error_msg
63
- except Exception as e:
64
- return None, f"❌ Error: {str(e)}"
65
-
66
- # Create Gradio interface
67
- with gr.Blocks(title="Video Audio Subtitle Stitcher", theme=gr.themes.Soft()) as app:
68
- gr.Markdown(
69
  """
70
- # 🎬 Video Audio Subtitle Stitcher
71
-
72
- **Upload your files and stitch them together - No local installation needed!**
73
-
74
- This app works entirely in your browser. Just upload, click stitch, and download your result.
75
  """
76
- )
77
-
78
- with gr.Row():
79
- with gr.Column():
80
- gr.Markdown("### πŸ“€ Upload Files")
81
 
82
- video_input = gr.File(
83
- label="πŸ“Ή Video File",
84
- file_types=[".mp4", ".mov", ".avi", ".mkv"],
85
- type="filepath"
86
- )
87
- audio_input = gr.File(
88
- label="🎡 Audio File",
89
- file_types=[".wav", ".mp3", ".aac", ".m4a"],
90
- type="filepath"
91
- )
92
- subtitle_input = gr.File(
93
- label="πŸ“ Subtitle File (.srt)",
94
- file_types=[".srt"],
95
- type="filepath"
96
- )
97
 
98
- gr.Markdown("### βš™οΈ Settings")
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
- crf_input = gr.Slider(
101
- minimum=18,
102
- maximum=28,
103
- value=23,
104
- step=1,
105
- label="Video Quality (CRF)",
106
- info="Lower = Better quality but larger file"
107
  )
108
 
109
- stitch_btn = gr.Button("🎬 Stitch Video", variant="primary", size="lg")
 
 
 
 
 
110
 
111
- gr.Markdown(
112
- """
113
- **πŸ’‘ Tips:**
114
- - CRF 18-20: Excellent quality
115
- - CRF 23: Balanced (recommended)
116
- - CRF 26-28: Smaller file size
117
- """
118
- )
119
-
120
- with gr.Column():
121
- gr.Markdown("### πŸ“₯ Output")
122
 
123
- status_output = gr.Textbox(
124
- label="Status",
125
- placeholder="Upload files and click 'Stitch Video' to begin...",
126
- lines=3
127
- )
128
- video_output = gr.Video(
129
- label="Result",
130
- autoplay=False
131
- )
132
 
133
- gr.Markdown(
134
- """
135
- **Download:** Right-click the video preview and "Save video as..."
136
- or use the download button in the video player.
137
- """
138
- )
139
 
140
- gr.Markdown(
141
- """
142
- ---
143
- ### πŸ“– How it works:
144
- 1. **Upload** your video, audio, and subtitle files
145
- 2. **Adjust** quality settings if needed
146
- 3. **Click** "Stitch Video" button
147
- 4. **Wait** for processing (may take a few moments)
148
- 5. **Preview** and download your result!
149
-
150
- ### 🎯 Technical Details:
151
- - Video codec: H.264 (libx264)
152
- - Audio codec: AAC
153
- - Output length: Matches shortest stream (video or audio)
154
- - Subtitles: Burned into video
155
-
156
- ### ☁️ Cloud Deployment Ready:
157
- This app can be deployed to Hugging Face Spaces, Google Colab, or any cloud platform!
158
- """
159
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
161
- # Connect the button to the function
162
- stitch_btn.click(
163
- fn=stitch_media,
164
- inputs=[video_input, audio_input, subtitle_input, crf_input],
165
- outputs=[video_output, status_output]
166
- )
167
 
168
  # Launch the app
169
  if __name__ == "__main__":
170
- app.launch()
 
9
  static_ffmpeg.add_paths()
10
 
11
  def stitch_media(video_file, audio_file, subtitle_file, crf_quality=23):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  """
13
+ Stitch video, audio, and subtitle files together using ffmpeg
14
+ All files are handled through Gradio's temporary file system
 
 
 
15
  """
16
+ try:
17
+ # Validate inputs
18
+ if not video_file or not audio_file or not subtitle_file:
19
+ return None, "❌ Please upload all three files (video, audio, subtitle)"
 
20
 
21
+ # Gradio automatically provides temporary file paths
22
+ video_path = video_file.name if hasattr(video_file, 'name') else video_file
23
+ audio_path = audio_file.name if hasattr(audio_file, 'name') else audio_file
24
+ subtitle_path = subtitle_file.name if hasattr(subtitle_file, 'name') else subtitle_file
25
+
26
+ # Create output file in temp directory
27
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
28
+ output_path = os.path.join(tempfile.gettempdir(), f"stitched_{timestamp}.mp4")
 
 
 
 
 
 
 
29
 
30
+ # FFmpeg command
31
+ cmd = [
32
+ "ffmpeg",
33
+ "-i", video_path,
34
+ "-i", audio_path,
35
+ "-vf", f"subtitles={subtitle_path}",
36
+ "-map", "0:v",
37
+ "-map", "1:a",
38
+ "-c:v", "libx264",
39
+ "-crf", str(crf_quality),
40
+ "-c:a", "aac",
41
+ "-y",
42
+ output_path
43
+ ]
44
 
45
+ # Execute ffmpeg
46
+ process = subprocess.run(
47
+ cmd,
48
+ check=True,
49
+ capture_output=True,
50
+ text=True
 
51
  )
52
 
53
+ # Check if output file was created
54
+ if os.path.exists(output_path):
55
+ file_size = os.path.getsize(output_path) / (1024 * 1024) # Size in MB
56
+ return output_path, f"βœ… Video stitched successfully! (Size: {file_size:.2f} MB)"
57
+ else:
58
+ return None, "❌ Output file was not created"
59
 
60
+ except subprocess.CalledProcessError as e:
61
+ error_msg = f"❌ FFmpeg error:\n{e.stderr[-500:]}" # Show last 500 chars of error
62
+ return None, error_msg
63
+ except Exception as e:
64
+ return None, f"❌ Error: {str(e)}"
65
+
66
+ # Create Gradio interface
67
+ with gr.Blocks(title="Video Audio Subtitle Stitcher", theme=gr.themes.Soft()) as app:
68
+ gr.Markdown(
69
+ """
70
+ # 🎬 Video Audio Subtitle Stitcher
71
 
72
+ **Upload your files and stitch them together - No local installation needed!**
 
 
 
 
 
 
 
 
73
 
74
+ This app works entirely in your browser. Just upload, click stitch, and download your result.
75
+ """
76
+ )
 
 
 
77
 
78
+ with gr.Row():
79
+ with gr.Column():
80
+ gr.Markdown("### πŸ“€ Upload Files")
81
+
82
+ video_input = gr.File(
83
+ label="πŸ“Ή Video File",
84
+ file_types=[".mp4", ".mov", ".avi", ".mkv"],
85
+ type="filepath"
86
+ )
87
+ audio_input = gr.File(
88
+ label="🎡 Audio File",
89
+ file_types=[".wav", ".mp3", ".aac", ".m4a"],
90
+ type="filepath"
91
+ )
92
+ subtitle_input = gr.File(
93
+ label="πŸ“ Subtitle File (.srt)",
94
+ file_types=[".srt"],
95
+ type="filepath"
96
+ )
97
+
98
+ gr.Markdown("### βš™οΈ Settings")
99
+
100
+ crf_input = gr.Slider(
101
+ minimum=18,
102
+ maximum=28,
103
+ value=23,
104
+ step=1,
105
+ label="Video Quality (CRF)",
106
+ info="Lower = Better quality but larger file"
107
+ )
108
+
109
+ stitch_btn = gr.Button("🎬 Stitch Video", variant="primary", size="lg")
110
+
111
+ gr.Markdown(
112
+ """
113
+ **πŸ’‘ Tips:**
114
+ - CRF 18-20: Excellent quality
115
+ - CRF 23: Balanced (recommended)
116
+ - CRF 26-28: Smaller file size
117
+ """
118
+ )
119
+
120
+ with gr.Column():
121
+ gr.Markdown("### πŸ“₯ Output")
122
+
123
+ status_output = gr.Textbox(
124
+ label="Status",
125
+ placeholder="Upload files and click 'Stitch Video' to begin...",
126
+ lines=3
127
+ )
128
+ video_output = gr.Video(
129
+ label="Result",
130
+ autoplay=False
131
+ )
132
+
133
+ gr.Markdown(
134
+ """
135
+ **Download:** Right-click the video preview and "Save video as..."
136
+ or use the download button in the video player.
137
+ """
138
+ )
139
+
140
+ gr.Markdown(
141
+ """
142
+ ---
143
+ ### πŸ“– How it works:
144
+ 1. **Upload** your video, audio, and subtitle files
145
+ 2. **Adjust** quality settings if needed
146
+ 3. **Click** "Stitch Video" button
147
+ 4. **Wait** for processing (may take a few moments)
148
+ 5. **Preview** and download your result!
149
+
150
+ ### 🎯 Technical Details:
151
+ - Video codec: H.264 (libx264)
152
+ - Audio codec: AAC
153
+ - Output length: Matches shortest stream (video or audio)
154
+ - Subtitles: Burned into video
155
+
156
+ ### ☁️ Cloud Deployment Ready:
157
+ This app can be deployed to Hugging Face Spaces, Google Colab, or any cloud platform!
158
+ """
159
+ )
160
 
161
+ # Connect the button to the function
162
+ stitch_btn.click(
163
+ fn=stitch_media,
164
+ inputs=[video_input, audio_input, subtitle_input, crf_input],
165
+ outputs=[video_output, status_output]
166
+ )
167
 
168
  # Launch the app
169
  if __name__ == "__main__":
170
+ app.launch()