RandomPersonRR commited on
Commit
b32dded
Β·
verified Β·
1 Parent(s): 6eeced8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +119 -94
app.py CHANGED
@@ -6,7 +6,7 @@ import glob
6
  import shutil
7
  import gradio as gr
8
 
9
- os.system("chmod +x fdkaac") # Ensure fdkaac is executable
10
 
11
  accel = 'auto'
12
  video_base_opts = ['-crf', '63', '-c:v', 'libx264', '-tune', 'zerolatency']
@@ -20,6 +20,7 @@ async def run_subprocess(cmd, use_fdkaac=False):
20
  env = os.environ.copy()
21
  if use_fdkaac:
22
  env["LD_LIBRARY_PATH"] = os.path.abspath("./") + ":" + env.get("LD_LIBRARY_PATH", "")
 
23
  process = await asyncio.create_subprocess_exec(
24
  *cmd,
25
  stdout=asyncio.subprocess.PIPE,
@@ -28,140 +29,164 @@ async def run_subprocess(cmd, use_fdkaac=False):
28
  )
29
  stdout, stderr = await process.communicate()
30
  if process.returncode != 0:
 
31
  raise subprocess.CalledProcessError(process.returncode, cmd, stderr.decode())
 
32
  return stdout.decode(), stderr.decode()
33
 
34
- async def convert_video_task(input_path, downscale, faster, use_mp3, audio_only, custom_bitrate, video_bitrate, progress):
35
  if use_mp3:
36
- progress.update(1, desc="Converting audio to MP3...")
37
  output_audio = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3")
38
- cmd = [
39
  'ffmpeg', '-y', '-i', input_path, '-vn',
40
  '-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1',
41
  output_audio
42
  ]
43
- await run_subprocess(cmd)
44
  if audio_only:
 
45
  return output_audio, None
46
- # embed into video
47
- progress.update(1, desc="Making the video quality lower...")
48
- output_video = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
49
- cmd = ['ffmpeg', '-y', '-hwaccel', accel, '-i', input_path]
50
- if custom_bitrate:
51
- cmd += ['-b:v', f"{int(video_bitrate)}k"]
52
  else:
53
- cmd += video_base_opts
54
- if faster:
55
- cmd += ['-preset', 'ultrafast']
56
- cmd += ['-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1', output_video]
57
- await run_subprocess(cmd)
58
- return None, output_video
59
-
60
- # split
61
- progress.update(1, desc="Splitting Audio and Video...")
62
- audio_wav = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.wav")
63
- await run_subprocess(['ffmpeg','-y','-i',input_path,'-ac','1','-ar','8000',audio_wav])
 
 
 
 
 
 
 
64
 
65
- # AAC encode
66
- progress.update(1, desc="Converting audio to AAC which is lower quality...")
67
  audio_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.m4a")
68
- await run_subprocess([ './fdkaac','-b','1k','-C','-f','2','-G','1','-w','8000','-o',audio_output,audio_wav ], use_fdkaac=True)
69
-
70
- # video
71
- progress.update(1, desc="Making the video quality lower...")
72
  video_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
73
- cmd = ['ffmpeg','-y','-hwaccel',accel,'-i',input_path]
 
 
 
 
 
 
 
 
 
 
74
  if downscale:
75
- cmd += ['-vf','scale=-2:144']
76
  if custom_bitrate:
77
- cmd += ['-b:v',f"{int(video_bitrate)}k"]
78
  else:
79
- cmd += video_base_opts
80
  if faster:
81
- cmd += ['-preset','ultrafast']
82
- cmd += ['-an',video_output]
83
- await run_subprocess(cmd)
84
 
85
  if audio_only:
86
  return audio_output, None
87
 
88
- # merge
89
- progress.update(1, desc="Mixing audio and video together...")
90
- merged = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
91
- await run_subprocess(['ffmpeg','-y','-i',video_output,'-i',audio_output,'-c','copy',merged])
92
 
93
- # cleanup
94
- for f in (audio_wav, audio_output, video_output):
95
- try: os.remove(f)
96
- except: pass
 
97
 
98
- return None, merged
99
 
100
- async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster,
101
- use_mp3, audio_only, custom_bitrate, video_bitrate,
102
- progress=gr.Progress()):
103
- with progress.tqdm(total=5) as pbar:
104
- # Step 1: fetch
105
  if use_youtube:
106
- pbar.update(1, desc="Downloading video...")
107
- yt_uuid = uuid.uuid4().hex
108
- out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s")
109
- await run_subprocess(['yt-dlp','-o',out,'-f','b',youtube_url])
110
- files = glob.glob(os.path.join(UPLOAD_FOLDER, yt_uuid + ".*"))
111
- if not files: return "Download failed.", None
 
 
 
 
112
  input_path = files[0]
113
  else:
114
- pbar.update(1, desc="Preparing input video...")
115
- fname = video_file.name
116
- ext = os.path.splitext(fname)[1]
117
- input_path = os.path.join(UPLOAD_FOLDER, uuid.uuid4().hex + ext)
118
- shutil.copy2(fname, input_path)
119
-
120
- # Step 2–5: convert
121
- if use_mp3:
122
- pbar.update(1, desc="Converting audio to MP3...")
123
- else:
124
- pbar.update(1, desc="Converting audio to AAC which is lower quality...")
125
  audio_out, video_out = await convert_video_task(
126
- input_path, downscale, faster, use_mp3, audio_only,
127
- custom_bitrate, video_bitrate, pbar
128
  )
129
 
130
- # final update
131
- pbar.update(1, desc="Finalizing...")
132
-
133
  if audio_only:
134
  return audio_out, audio_out
135
  return video_out, video_out
 
 
 
 
 
136
 
137
- # Build UI
138
  with gr.Blocks(theme=gr.themes.Default(primary_hue="rose")) as demo:
139
- gr.Markdown("# Low Quality Video Inator")
140
- with gr.Row():
141
- use_youtube = gr.Checkbox(label="Use YouTube URL", value=False)
142
- youtube_url = gr.Textbox(label="YouTube URL")
143
- video_file = gr.File(label="Upload Video")
144
-
145
- with gr.Row():
146
- downscale = gr.Checkbox("Downscale Video to 144p", value=False)
147
- faster = gr.Checkbox("Faster Compression", value=False)
148
- with gr.Row():
149
- use_mp3 = gr.Checkbox("Use MP3 Audio", value=False)
150
- audio_only = gr.Checkbox("Audio Only", value=False)
151
- with gr.Row():
152
- custom_bitrate = gr.Checkbox("Custom Video Bitrate", value=False)
153
- video_bitrate = gr.Number(label="Bitrate (kbps)", visible=False)
154
- custom_bitrate.change(lambda x: gr.update(visible=x), custom_bitrate, video_bitrate)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
  convert_button = gr.Button("Convert Now", variant="primary")
157
- video_preview = gr.Video()
158
- file_download = gr.File()
 
 
 
 
159
 
160
  convert_button.click(
161
- process_conversion,
162
- inputs=[use_youtube, youtube_url, video_file,
163
- downscale, faster, use_mp3, audio_only,
164
- custom_bitrate, video_bitrate],
 
 
165
  outputs=[video_preview, file_download]
166
  )
167
 
 
6
  import shutil
7
  import gradio as gr
8
 
9
+ os.system("chmod +x fdkaac") # Make sure fdkaac is executable
10
 
11
  accel = 'auto'
12
  video_base_opts = ['-crf', '63', '-c:v', 'libx264', '-tune', 'zerolatency']
 
20
  env = os.environ.copy()
21
  if use_fdkaac:
22
  env["LD_LIBRARY_PATH"] = os.path.abspath("./") + ":" + env.get("LD_LIBRARY_PATH", "")
23
+ print(f"[DEBUG] Running command:\n{' '.join(cmd)}\n")
24
  process = await asyncio.create_subprocess_exec(
25
  *cmd,
26
  stdout=asyncio.subprocess.PIPE,
 
29
  )
30
  stdout, stderr = await process.communicate()
31
  if process.returncode != 0:
32
+ print(f"[ERROR] Command failed:\n{stderr.decode()}\n")
33
  raise subprocess.CalledProcessError(process.returncode, cmd, stderr.decode())
34
+ print(f"[DEBUG] Command succeeded:\n{stdout.decode()}\n")
35
  return stdout.decode(), stderr.decode()
36
 
37
+ async def convert_video_task(input_path, downscale, faster, use_mp3, audio_only, custom_bitrate, video_bitrate):
38
  if use_mp3:
 
39
  output_audio = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3")
40
+ ffmpeg_audio_cmd = [
41
  'ffmpeg', '-y', '-i', input_path, '-vn',
42
  '-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1',
43
  output_audio
44
  ]
 
45
  if audio_only:
46
+ await run_subprocess(ffmpeg_audio_cmd)
47
  return output_audio, None
 
 
 
 
 
 
48
  else:
49
+ output_video = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
50
+ ffmpeg_video_cmd = [
51
+ 'ffmpeg', '-y', '-hwaccel', accel, '-i', input_path
52
+ ]
53
+
54
+ if custom_bitrate:
55
+ ffmpeg_video_cmd += ['-b:v', f"{int(video_bitrate)}k"]
56
+ else:
57
+ ffmpeg_video_cmd += video_base_opts
58
+ if faster:
59
+ ffmpeg_video_cmd.extend(['-preset', 'ultrafast'])
60
+
61
+ ffmpeg_video_cmd += [
62
+ '-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1',
63
+ output_video
64
+ ]
65
+ await run_subprocess(ffmpeg_video_cmd)
66
+ return None, output_video
67
 
68
+ audio_wav = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.wav")
 
69
  audio_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.m4a")
 
 
 
 
70
  video_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
71
+
72
+ await run_subprocess([
73
+ 'ffmpeg', '-y', '-i', input_path, '-ac', '1', '-ar', '8000', audio_wav
74
+ ])
75
+
76
+ await run_subprocess([
77
+ './fdkaac', '-b', '1k', '-C', '-f', '2', '-G', '1', '-w', '8000',
78
+ '-o', audio_output, audio_wav
79
+ ], use_fdkaac=True)
80
+
81
+ video_cmd = ['ffmpeg', '-y', '-hwaccel', accel, '-i', input_path]
82
  if downscale:
83
+ video_cmd += ['-vf', 'scale=-2:144']
84
  if custom_bitrate:
85
+ video_cmd += ['-b:v', f"{int(video_bitrate)}k"]
86
  else:
87
+ video_cmd += video_base_opts
88
  if faster:
89
+ video_cmd.extend(['-preset', 'ultrafast'])
90
+ video_cmd += ['-an', video_output]
91
+ await run_subprocess(video_cmd)
92
 
93
  if audio_only:
94
  return audio_output, None
95
 
96
+ merged_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
97
+ await run_subprocess([
98
+ 'ffmpeg', '-y', '-i', video_output, '-i', audio_output, '-c', 'copy', merged_output
99
+ ])
100
 
101
+ for f in [audio_wav, audio_output, video_output]:
102
+ try:
103
+ os.remove(f)
104
+ except FileNotFoundError:
105
+ pass
106
 
107
+ return None, merged_output
108
 
109
+ async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only, custom_bitrate, video_bitrate):
110
+ try:
 
 
 
111
  if use_youtube:
112
+ if not youtube_url:
113
+ return "Error: YouTube URL required.", None
114
+ yt_uuid = str(uuid.uuid4())
115
+ yt_out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s")
116
+ yt_cmd = ['yt-dlp', '-o', yt_out, '-f', 'b', youtube_url]
117
+ await run_subprocess(yt_cmd)
118
+ pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*")
119
+ files = glob.glob(pattern)
120
+ if not files:
121
+ return "Download failed.", None
122
  input_path = files[0]
123
  else:
124
+ if not video_file:
125
+ return "No video provided.", None
126
+ ext = os.path.splitext(video_file.name)[1]
127
+ input_path = os.path.join(UPLOAD_FOLDER, f"{uuid.uuid4()}{ext}")
128
+ shutil.copy2(video_file.name, input_path)
129
+
 
 
 
 
 
130
  audio_out, video_out = await convert_video_task(
131
+ input_path, downscale, faster, use_mp3, audio_only, custom_bitrate, video_bitrate
 
132
  )
133
 
 
 
 
134
  if audio_only:
135
  return audio_out, audio_out
136
  return video_out, video_out
137
+ except Exception as e:
138
+ return f"Error: {str(e)}", None
139
+
140
+ def convert_video(*args):
141
+ return asyncio.run(process_conversion(*args))
142
 
 
143
  with gr.Blocks(theme=gr.themes.Default(primary_hue="rose")) as demo:
144
+ gr.Markdown("""
145
+ # **Low Quality Video Inator**
146
+
147
+ Upload a video or paste a YouTube URL below, then tweak the settings.
148
+ **Note:** YouTube downloads almost never work on HuggingFace.
149
+ """)
150
+
151
+ with gr.Group():
152
+ with gr.Row():
153
+ use_youtube = gr.Checkbox(label="πŸ”— Use YouTube URL (usually broken here)", value=False)
154
+ youtube_url = gr.Textbox(label="YouTube URL", placeholder="Paste YouTube URL here")
155
+ video_file = gr.File(label="πŸ“ Upload Video File")
156
+
157
+ gr.Markdown("### βš™οΈ **Conversion Settings**")
158
+ with gr.Group():
159
+ with gr.Row():
160
+ downscale = gr.Checkbox(label="Downscale Video to 144p", value=False)
161
+ faster = gr.Checkbox(label="Faster Video Compression (pixelated, faster)", value=False)
162
+ with gr.Row():
163
+ use_mp3 = gr.Checkbox(label="Use MP3 Audio (better compatibility, worse quality)", value=False)
164
+ audio_only = gr.Checkbox(label="Audio Only (no video output)", value=False)
165
+ with gr.Row():
166
+ custom_bitrate = gr.Checkbox(label="Use Custom Video Bitrate", value=False)
167
+ video_bitrate = gr.Number(label="Video Bitrate (kbps)", visible=False)
168
+
169
+ custom_bitrate.change(
170
+ lambda checked: gr.update(visible=checked),
171
+ inputs=[custom_bitrate],
172
+ outputs=[video_bitrate]
173
+ )
174
 
175
  convert_button = gr.Button("Convert Now", variant="primary")
176
+
177
+ gr.Markdown("### **Conversion Preview**")
178
+ video_preview = gr.Video(label="Preview Output")
179
+
180
+ gr.Markdown("### **Download Your Masterpiece**")
181
+ file_download = gr.File(label="Download Result")
182
 
183
  convert_button.click(
184
+ convert_video,
185
+ inputs=[
186
+ use_youtube, youtube_url, video_file,
187
+ downscale, faster, use_mp3, audio_only,
188
+ custom_bitrate, video_bitrate
189
+ ],
190
  outputs=[video_preview, file_download]
191
  )
192