RandomPersonRR commited on
Commit
6567ae9
·
verified ·
1 Parent(s): 8905498

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -96
app.py CHANGED
@@ -1,129 +1,116 @@
1
  import os
 
2
  import subprocess
3
  import uuid
4
  import glob
5
  import shutil
6
  import gradio as gr
7
 
8
- os.system("chmod +x ffmpeg")
9
- # Set default acceleration and extra encoding options.
10
  accel = 'auto'
11
- extra = '-crf 63 -c:v libx264' # default extra settings
12
 
13
- # Fixed upload and conversion folders.
14
  UPLOAD_FOLDER = 'uploads'
15
  CONVERTED_FOLDER = 'converted'
16
  os.makedirs(UPLOAD_FOLDER, exist_ok=True)
17
  os.makedirs(CONVERTED_FOLDER, exist_ok=True)
18
 
19
- # Helper function to configure audio options.
20
- def configure_audio(cmd_list, use_mp3):
21
- if use_mp3:
22
- cmd_list.extend(['-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24k', '-ac', '1'])
23
- else:
24
- cmd_list.extend(['-c:a', 'aac', '-b:a', '1k', '-ar', '8k', '-ac', '1'])
25
-
26
- def convert_video(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only):
27
- """
28
- Converts a video either from a YouTube URL or an uploaded file.
29
- Returns a tuple (preview_file, download_file) with the output path.
30
- """
31
- # Determine output filename based on whether only audio is desired.
32
- if audio_only:
33
- output_filename = f"{uuid.uuid4()}.mp3" if use_mp3 else f"{uuid.uuid4()}.aac"
34
- else:
35
- output_filename = f"{uuid.uuid4()}.mp4"
36
- output_path = os.path.join(CONVERTED_FOLDER, output_filename)
37
-
38
- if use_youtube:
39
- if not youtube_url:
40
- return "Error: YouTube URL is required.", None
41
-
42
- quality = 'worstaudio' if audio_only and downscale else (
43
- 'worstvideo+worstaudio' if downscale else 'b')
44
-
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
- pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*")
55
- downloaded_files = glob.glob(pattern)
56
- if not downloaded_files:
57
- return "Failed to download YouTube video.", None
58
- input_path = downloaded_files[0]
59
- else:
60
- if not video_file:
61
- return "Error: No video file provided.", None
62
- if os.path.exists(video_file):
63
- ext = os.path.splitext(video_file)[1]
64
- input_filename = f"{uuid.uuid4()}{ext}"
65
- input_path = os.path.join(UPLOAD_FOLDER, input_filename)
66
- shutil.copy2(video_file, input_path)
67
- else:
68
- input_path = video_file
69
-
70
- # Handle optional downscale first
71
- if downscale and not audio_only:
72
- downscaled_path = os.path.join(UPLOAD_FOLDER, f"downscaled_{uuid.uuid4()}.mp4")
73
- downscale_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', input_path,
74
- '-vf', 'scale=144:-2', '-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '40',
75
- '-c:a', 'copy', downscaled_path]
76
- try:
77
- subprocess.run(downscale_cmd, check=True)
78
- except subprocess.CalledProcessError as e:
79
- return f"An error occurred during downscaling: {e}", None
80
- input_path = downscaled_path # Use this for next pass
81
-
82
- # Now do the final encode
83
- ffmpeg_cmd = ['./ffmpeg', '-hwaccel', accel, '-y', '-i', input_path] + extra.split()
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  if faster:
86
- ffmpeg_cmd.extend(['-preset', 'ultrafast'])
 
87
 
88
- if audio_only:
89
- ffmpeg_cmd.extend(['-vn'])
90
- configure_audio(ffmpeg_cmd, use_mp3)
91
-
92
- ffmpeg_cmd.append(output_path)
93
 
 
94
  try:
95
- subprocess.run(ffmpeg_cmd, check=True)
96
- except subprocess.CalledProcessError as e:
97
- return f"An error occurred during conversion: {e}", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
99
- return output_path, output_path
 
100
 
101
- # Create the Gradio interface.
102
  with gr.Blocks() as demo:
103
  gr.Markdown("## Low Quality Video Inator")
104
  gr.Markdown("Upload a video or use a YouTube URL and adjust the options below.")
105
-
106
  with gr.Row():
107
- use_youtube = gr.Checkbox(label="Use YouTube URL (almost never works)", value=False)
108
- youtube_url = gr.Textbox(label="YouTube URL", placeholder="Enter YouTube URL here")
109
  video_file = gr.File(label="Upload Video")
110
-
111
  with gr.Row():
112
  downscale = gr.Checkbox(label="Downscale Video (144p)", value=False)
113
- faster = gr.Checkbox(label="Faster Conversion (more pixelated)", value=False)
114
  with gr.Row():
115
- use_mp3 = gr.Checkbox(label="Use MP3 (video audio compression)", value=False)
116
- audio_only = gr.Checkbox(label="Only Audio (no video)", value=False)
117
-
118
- convert_button = gr.Button("Convert Video")
119
-
120
- gr.Markdown("### Preview Converted Video")
121
- video_preview = gr.Video(label="Converted Video")
122
- gr.Markdown("### Download Converted Video")
123
- file_download = gr.File(label="Download Video")
124
-
125
  convert_button.click(
126
- convert_video,
127
  inputs=[use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only],
128
  outputs=[video_preview, file_download]
129
  )
 
1
  import os
2
+ import asyncio
3
  import subprocess
4
  import uuid
5
  import glob
6
  import shutil
7
  import gradio as gr
8
 
 
 
9
  accel = 'auto'
10
+ video_extra = ['-crf', '63', '-c:v', 'libx264', '-preset', 'ultrafast', '-tune', 'zerolatency']
11
 
 
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
+ async def run_subprocess(cmd):
18
+ process = await asyncio.create_subprocess_exec(
19
+ *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
20
+ )
21
+ stdout, stderr = await process.communicate()
22
+ if process.returncode != 0:
23
+ raise subprocess.CalledProcessError(process.returncode, cmd, stderr.decode())
24
+ return stdout.decode(), stderr.decode()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ async def convert_video_task(input_path, downscale, faster, use_mp3):
27
+ if use_mp3:
28
+ # Directly compress audio to MP3 with video untouched or skipped
29
+ output_path = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3")
30
+ ffmpeg_cmd = ['ffmpeg', '-y', '-i', input_path, '-vn',
31
+ '-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1', output_path]
32
+ await run_subprocess(ffmpeg_cmd)
33
+ return output_path, None # No video output in this case
34
+
35
+ # Non-MP3 path: split streams
36
+ audio_wav = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.wav")
37
+ audio_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.m4a")
38
+ video_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
39
+
40
+ # Extract mono WAV
41
+ await run_subprocess([
42
+ 'ffmpeg', '-y', '-i', input_path, '-ac', '1', '-ar', '8000', audio_wav
43
+ ])
44
+
45
+ # Compress with fdkaac
46
+ await run_subprocess([
47
+ 'fdkaac', '-b', '1k', '-C', '-f', '2', '-G', '1', '-w', '8000',
48
+ '-o', audio_output, audio_wav
49
+ ])
50
+
51
+ # Video compression
52
+ video_cmd = ['ffmpeg', '-y', '-hwaccel', accel, '-i', input_path, *video_extra, '-an', video_output]
53
  if faster:
54
+ video_cmd.extend(['-preset', 'ultrafast'])
55
+ await run_subprocess(video_cmd)
56
 
57
+ return audio_output, video_output
 
 
 
 
58
 
59
+ async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only):
60
  try:
61
+ if use_youtube:
62
+ yt_uuid = str(uuid.uuid4())
63
+ yt_out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s")
64
+ yt_cmd = ['yt-dlp', '-o', yt_out, '-f', 'b', youtube_url]
65
+ await run_subprocess(yt_cmd)
66
+ pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*")
67
+ files = glob.glob(pattern)
68
+ if not files:
69
+ return "Download failed.", None
70
+ input_path = files[0]
71
+ else:
72
+ if not video_file:
73
+ return "No video provided.", None
74
+ ext = os.path.splitext(video_file)[1]
75
+ input_path = os.path.join(UPLOAD_FOLDER, f"{uuid.uuid4()}{ext}")
76
+ shutil.copy2(video_file, input_path)
77
+
78
+ audio_out, video_out = await convert_video_task(input_path, downscale, faster, use_mp3)
79
+
80
+ if audio_only:
81
+ return audio_out, audio_out
82
+ return video_out or audio_out, video_out or audio_out
83
+ except Exception as e:
84
+ return str(e), None
85
 
86
+ def convert_video(*args):
87
+ return asyncio.run(process_conversion(*args))
88
 
89
+ # Gradio Interface
90
  with gr.Blocks() as demo:
91
  gr.Markdown("## Low Quality Video Inator")
92
  gr.Markdown("Upload a video or use a YouTube URL and adjust the options below.")
93
+
94
  with gr.Row():
95
+ use_youtube = gr.Checkbox(label="Use YouTube URL", value=False)
96
+ youtube_url = gr.Textbox(label="YouTube URL")
97
  video_file = gr.File(label="Upload Video")
98
+
99
  with gr.Row():
100
  downscale = gr.Checkbox(label="Downscale Video (144p)", value=False)
101
+ faster = gr.Checkbox(label="Faster Conversion", value=False)
102
  with gr.Row():
103
+ use_mp3 = gr.Checkbox(label="Use MP3 (skips video compression)", value=False)
104
+ audio_only = gr.Checkbox(label="Only Audio", value=False)
105
+
106
+ convert_button = gr.Button("Convert")
107
+ gr.Markdown("### Preview")
108
+ video_preview = gr.Video()
109
+ gr.Markdown("### Download")
110
+ file_download = gr.File()
111
+
 
112
  convert_button.click(
113
+ convert_video,
114
  inputs=[use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only],
115
  outputs=[video_preview, file_download]
116
  )