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)