Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -2,13 +2,29 @@ import gradio as gr
|
|
2 |
import subprocess
|
3 |
import os
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
def compress_video(video_file):
|
|
|
6 |
if video_file is None:
|
7 |
-
|
|
|
8 |
|
9 |
try:
|
10 |
-
# Get the input file path
|
11 |
input_path = video_file
|
|
|
12 |
|
13 |
# Create output filename - in the same directory as input
|
14 |
base_dir = os.path.dirname(input_path)
|
@@ -27,6 +43,9 @@ def compress_video(video_file):
|
|
27 |
output_path
|
28 |
]
|
29 |
|
|
|
|
|
|
|
30 |
# Run the command
|
31 |
process = subprocess.Popen(
|
32 |
command,
|
@@ -36,21 +55,34 @@ def compress_video(video_file):
|
|
36 |
stdout, stderr = process.communicate()
|
37 |
|
38 |
if process.returncode != 0:
|
39 |
-
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
-
#
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
except Exception as e:
|
45 |
-
|
|
|
46 |
|
47 |
-
with gr.Blocks() as app:
|
48 |
gr.Markdown("# Video Compression with FFmpeg")
|
49 |
gr.Markdown("""
|
50 |
-
This app compresses videos using FFmpeg with the following parameters:
|
51 |
-
```
|
52 |
-
ffmpeg -i input.mp4 -vcodec libx264 -crf 28 -vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" -y output.mp4
|
53 |
-
```
|
54 |
- Uses H.264 codec
|
55 |
- CRF 28 (higher values = more compression, lower quality)
|
56 |
- Pads dimensions to ensure they're even numbers (required by some codecs)
|
@@ -59,17 +91,25 @@ with gr.Blocks() as app:
|
|
59 |
with gr.Row():
|
60 |
with gr.Column():
|
61 |
input_video = gr.Video(label="Upload Video")
|
|
|
62 |
compress_btn = gr.Button("Compress Video", variant="primary")
|
63 |
|
64 |
with gr.Column():
|
65 |
output_video = gr.Video(label="Compressed Video")
|
66 |
-
|
|
|
67 |
|
68 |
compress_btn.click(
|
69 |
-
fn=compress_video,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
inputs=[input_video],
|
71 |
-
outputs=[
|
72 |
)
|
73 |
|
74 |
-
|
75 |
-
app.launch()
|
|
|
2 |
import subprocess
|
3 |
import os
|
4 |
|
5 |
+
def get_file_size(file_path):
|
6 |
+
"""Get file size in a human-readable format"""
|
7 |
+
if not file_path or not os.path.exists(file_path):
|
8 |
+
return "N/A"
|
9 |
+
|
10 |
+
size_bytes = os.path.getsize(file_path)
|
11 |
+
|
12 |
+
# Convert to appropriate unit
|
13 |
+
for unit in ['B', 'KB', 'MB', 'GB']:
|
14 |
+
if size_bytes < 1024 or unit == 'GB':
|
15 |
+
return f"{size_bytes:.2f} {unit}"
|
16 |
+
size_bytes /= 1024
|
17 |
+
|
18 |
def compress_video(video_file):
|
19 |
+
"""Compresses the uploaded video using FFmpeg and returns the output video path and file sizes."""
|
20 |
if video_file is None:
|
21 |
+
gr.Info("No video uploaded")
|
22 |
+
return None, "N/A", "N/A", 0
|
23 |
|
24 |
try:
|
25 |
+
# Get the input file path and size
|
26 |
input_path = video_file
|
27 |
+
input_size = get_file_size(input_path)
|
28 |
|
29 |
# Create output filename - in the same directory as input
|
30 |
base_dir = os.path.dirname(input_path)
|
|
|
43 |
output_path
|
44 |
]
|
45 |
|
46 |
+
# Show processing notification
|
47 |
+
gr.Info("Processing video...")
|
48 |
+
|
49 |
# Run the command
|
50 |
process = subprocess.Popen(
|
51 |
command,
|
|
|
55 |
stdout, stderr = process.communicate()
|
56 |
|
57 |
if process.returncode != 0:
|
58 |
+
error_message = stderr.decode()
|
59 |
+
gr.Info(f"Error: FFmpeg operation failed. Error message: {error_message}")
|
60 |
+
return None, input_size, "N/A", 0
|
61 |
+
|
62 |
+
# Calculate output size and savings
|
63 |
+
output_size = get_file_size(output_path)
|
64 |
|
65 |
+
# Calculate compression percentage
|
66 |
+
input_bytes = os.path.getsize(input_path)
|
67 |
+
output_bytes = os.path.getsize(output_path)
|
68 |
+
if input_bytes > 0:
|
69 |
+
compression_percent = (1 - (output_bytes / input_bytes)) * 100
|
70 |
+
else:
|
71 |
+
compression_percent = 0
|
72 |
+
|
73 |
+
# Show success notification
|
74 |
+
gr.Info(f"Video compressed successfully! Saved {compression_percent:.1f}% of original size")
|
75 |
+
|
76 |
+
# Return the processed video file and size information
|
77 |
+
return output_path, input_size, output_size, round(compression_percent, 1)
|
78 |
|
79 |
except Exception as e:
|
80 |
+
gr.Info(f"An error occurred: {str(e)}")
|
81 |
+
return None, get_file_size(video_file) if video_file else "N/A", "N/A", 0
|
82 |
|
83 |
+
with gr.Blocks(theme=gr.themes.Soft()) as app:
|
84 |
gr.Markdown("# Video Compression with FFmpeg")
|
85 |
gr.Markdown("""
|
|
|
|
|
|
|
|
|
86 |
- Uses H.264 codec
|
87 |
- CRF 28 (higher values = more compression, lower quality)
|
88 |
- Pads dimensions to ensure they're even numbers (required by some codecs)
|
|
|
91 |
with gr.Row():
|
92 |
with gr.Column():
|
93 |
input_video = gr.Video(label="Upload Video")
|
94 |
+
input_size_display = gr.Textbox(label="Input File Size", interactive=False)
|
95 |
compress_btn = gr.Button("Compress Video", variant="primary")
|
96 |
|
97 |
with gr.Column():
|
98 |
output_video = gr.Video(label="Compressed Video")
|
99 |
+
output_size_display = gr.Textbox(label="Output File Size", interactive=False)
|
100 |
+
compression_ratio = gr.Number(label="Space Saved (%)", interactive=False)
|
101 |
|
102 |
compress_btn.click(
|
103 |
+
fn=compress_video,
|
104 |
+
inputs=[input_video],
|
105 |
+
outputs=[output_video, input_size_display, output_size_display, compression_ratio]
|
106 |
+
)
|
107 |
+
|
108 |
+
# Also update input size when video is uploaded
|
109 |
+
input_video.change(
|
110 |
+
fn=lambda video: get_file_size(video) if video else "N/A",
|
111 |
inputs=[input_video],
|
112 |
+
outputs=[input_size_display]
|
113 |
)
|
114 |
|
115 |
+
app.launch()
|
|