RandomPersonRR commited on
Commit
d83b57c
·
verified ·
1 Parent(s): 566bf5a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import subprocess
3
+ import uuid
4
+ import glob
5
+ import gradio as gr
6
+
7
+ # Set default acceleration and extra encoding options.
8
+ accel = 'auto'
9
+ extra = '-crf 63 -c:v libx264' # default extra settings
10
+
11
+ # For simplicity, we use fixed upload and conversion folders.
12
+ UPLOAD_FOLDER = 'uploads'
13
+ CONVERTED_FOLDER = 'converted'
14
+ os.makedirs(UPLOAD_FOLDER, exist_ok=True)
15
+ os.makedirs(CONVERTED_FOLDER, exist_ok=True)
16
+
17
+ # Helper function to configure audio options.
18
+ def configure_audio(cmd_list, use_mp3):
19
+ if use_mp3:
20
+ cmd_list.extend(['-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24k', '-ac', '1'])
21
+ else:
22
+ cmd_list.extend(['-c:a', 'aac', '-b:a', '1k', '-ar', '8k', '-ac', '1'])
23
+
24
+ def convert_video(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only):
25
+ """
26
+ Converts a video either from a YouTube URL or an uploaded file.
27
+ Returns a tuple (preview_file, download_file) with the output path.
28
+ """
29
+ # Determine output filename based on whether only audio is desired.
30
+ if audio_only:
31
+ output_filename = f"{uuid.uuid4()}.mp3" if use_mp3 else f"{uuid.uuid4()}.aac"
32
+ else:
33
+ output_filename = f"{uuid.uuid4()}.mp4"
34
+ output_path = os.path.join(CONVERTED_FOLDER, output_filename)
35
+
36
+ files_to_delete = [] # List to keep track of temporary files.
37
+
38
+ if use_youtube:
39
+ if not youtube_url:
40
+ return "Error: YouTube URL is required.", None
41
+
42
+ if downscale:
43
+ # Download the worst-quality version to disk.
44
+ quality = 'worstaudio' if audio_only else 'worstvideo+worstaudio'
45
+ yt_uuid = str(uuid.uuid4())
46
+ yt_input_filename = yt_uuid + ".%(ext)s"
47
+ yt_input_path = os.path.join(UPLOAD_FOLDER, yt_input_filename)
48
+ yt_dlp_cmd = ['yt-dlp', '-o', yt_input_path, '-f', quality, youtube_url]
49
+ try:
50
+ subprocess.run(yt_dlp_cmd, check=True)
51
+ except subprocess.CalledProcessError as e:
52
+ return f"An error occurred during YouTube download: {e}", None
53
+
54
+ # Locate the downloaded file (yt-dlp replaces %(ext)s with the actual extension).
55
+ pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*")
56
+ downloaded_files = glob.glob(pattern)
57
+ if not downloaded_files:
58
+ return "Failed to download YouTube video.", None
59
+ yt_input_file = downloaded_files[0]
60
+ files_to_delete.append(yt_input_file)
61
+ ffmpeg_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', yt_input_file] + extra.split()
62
+ else:
63
+ # Pipe best-quality output directly from yt-dlp.
64
+ quality = 'bestaudio' if audio_only else 'best'
65
+ yt_dlp_cmd = ['yt-dlp', '-o', '-', '-f', quality, youtube_url]
66
+ ffmpeg_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', '-'] + extra.split()
67
+ else:
68
+ # File upload branch.
69
+ if not video_file:
70
+ return "Error: No video file provided.", None
71
+ # Gradio passes the file path as a string.
72
+ ext = os.path.splitext(video_file)[1]
73
+ input_filename = f"{uuid.uuid4()}{ext}"
74
+ input_path = os.path.join(UPLOAD_FOLDER, input_filename)
75
+ # Move the uploaded file to our upload folder.
76
+ os.rename(video_file, input_path)
77
+ files_to_delete.append(input_path)
78
+ ffmpeg_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', input_path] + extra.split()
79
+
80
+ # Apply downscale if requested (for file uploads and YouTube downloads alike).
81
+ if downscale:
82
+ ffmpeg_cmd.extend(['-vf', 'scale=144:-2'])
83
+ # Apply faster conversion if selected.
84
+ if faster:
85
+ ffmpeg_cmd.extend(['-preset', 'ultrafast'])
86
+
87
+ # Configure audio options.
88
+ if audio_only:
89
+ ffmpeg_cmd.extend(['-vn'])
90
+ configure_audio(ffmpeg_cmd, use_mp3)
91
+ else:
92
+ configure_audio(ffmpeg_cmd, use_mp3)
93
+
94
+ ffmpeg_cmd.append(output_path)
95
+
96
+ # Run FFmpeg.
97
+ if use_youtube and not downscale:
98
+ try:
99
+ yt_proc = subprocess.Popen(yt_dlp_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
100
+ subprocess.run(ffmpeg_cmd, stdin=yt_proc.stdout, check=True)
101
+ yt_proc.stdout.close()
102
+ yt_proc.wait()
103
+ except subprocess.CalledProcessError as e:
104
+ return f"An error occurred during conversion: {e}", None
105
+ else:
106
+ try:
107
+ subprocess.run(ffmpeg_cmd, check=True)
108
+ except subprocess.CalledProcessError as e:
109
+ return f"An error occurred during conversion: {e}", None
110
+
111
+ # (Optional cleanup could be done here for files in files_to_delete.)
112
+ # Return the output file path for both video preview and file download.
113
+ return output_path, output_path
114
+
115
+ # Create the Gradio interface using Blocks.
116
+ with gr.Blocks() as demo:
117
+ gr.Markdown("## Low Quality Video Inator")
118
+ gr.Markdown("Upload a video or use a YouTube URL and adjust the options below.")
119
+
120
+ with gr.Row():
121
+ use_youtube = gr.Checkbox(label="Use YouTube URL", value=False)
122
+ youtube_url = gr.Textbox(label="YouTube URL", placeholder="Enter YouTube URL here")
123
+ video_file = gr.File(label="Upload Video")
124
+
125
+ with gr.Row():
126
+ downscale = gr.Checkbox(label="Downscale Video (144p)", value=False)
127
+ faster = gr.Checkbox(label="Faster Conversion (more pixelated)", value=False)
128
+ with gr.Row():
129
+ use_mp3 = gr.Checkbox(label="Use MP3 (video audio compression)", value=False)
130
+ audio_only = gr.Checkbox(label="Only Audio (no video)", value=False)
131
+
132
+ convert_button = gr.Button("Convert Video")
133
+
134
+ gr.Markdown("### Preview Converted Video")
135
+ video_preview = gr.Video(label="Converted Video")
136
+ gr.Markdown("### Download Converted Video")
137
+ file_download = gr.File(label="Download Video")
138
+
139
+ convert_button.click(
140
+ convert_video,
141
+ inputs=[use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only],
142
+ outputs=[video_preview, file_download]
143
+ )
144
+
145
+ demo.launch()