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