Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -36,6 +36,29 @@ def get_output_path(input_path, temp_dir, res):
|
|
36 |
output_path = temp_dir / (Path(input_path).stem + f"_{res}.m3u8")
|
37 |
return output_path
|
38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
39 |
|
40 |
def get_aspect_ratio(input_path, aspect_ratio):
|
41 |
"""Returns the aspect ratio of the video, calculating it if necessary."""
|
@@ -61,6 +84,16 @@ def upload_to_web3_storage(api_key, path):
|
|
61 |
logging.exception("An error occurred while uploading to web3.storage.")
|
62 |
return f"An error occurred while uploading to web3.storage: {response.json()}"
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
def convert_video(video_file, quality, aspect_ratio, video_url, api_key, upload):
|
65 |
standard_resolutions = [4320, 2160, 1440, 1080, 720, 480] # 8K, 4K, 2K, Full HD, HD, SD in pixels
|
66 |
|
@@ -88,18 +121,17 @@ def convert_video(video_file, quality, aspect_ratio, video_url, api_key, upload)
|
|
88 |
"-vf", f"scale={scale},setsar={aspect_ratio}", "-hls_time", "6",
|
89 |
"-hls_playlist_type", "vod", "-f", "hls", str(output_path)
|
90 |
]
|
91 |
-
|
92 |
try:
|
93 |
-
|
|
|
94 |
except subprocess.CalledProcessError as e:
|
95 |
logging.exception("ffmpeg command failed.")
|
96 |
-
error_file_path =
|
97 |
with open(error_file_path, 'w') as error_file:
|
98 |
-
error_file.write("ffmpeg command failed
|
99 |
-
error_file.write(e.stdout.decode())
|
100 |
error_file.write(e.stderr.decode())
|
101 |
return error_file_path
|
102 |
-
|
103 |
except subprocess.TimeoutExpired:
|
104 |
logging.exception("ffmpeg command timed out.")
|
105 |
return "ffmpeg command timed out."
|
@@ -115,12 +147,16 @@ def convert_video(video_file, quality, aspect_ratio, video_url, api_key, upload)
|
|
115 |
if not output_paths:
|
116 |
return "The video is smaller than the smallest standard resolution."
|
117 |
|
|
|
|
|
|
|
118 |
output_copy_paths = [shutil.copy2(path, tempfile.gettempdir()) for path in output_paths]
|
|
|
119 |
|
120 |
if upload:
|
121 |
-
return [upload_to_web3_storage(api_key, path) for path in output_copy_paths]
|
122 |
else:
|
123 |
-
return output_copy_paths
|
124 |
|
125 |
|
126 |
def main():
|
@@ -132,8 +168,6 @@ def main():
|
|
132 |
"1.85:1", "2.35:1", "3:1", "360", "9:16", "16:9",
|
133 |
"2:1", "1:2", "9:1"],
|
134 |
label="Aspect Ratio", default="16:9")
|
135 |
-
# resolution = gr.components.Dropdown(
|
136 |
-
# choices=["480p", "720p", "1080p", "1440p", "2160p", "4320p"], label="Resolution", default="1080p")
|
137 |
video_url = gr.inputs.Textbox(label="Video URL")
|
138 |
api_key = gr.inputs.Textbox(label="web3.storage API Key")
|
139 |
upload = gr.inputs.Checkbox(label="Upload to web3.storage", default=False)
|
|
|
36 |
output_path = temp_dir / (Path(input_path).stem + f"_{res}.m3u8")
|
37 |
return output_path
|
38 |
|
39 |
+
def process_output(output):
|
40 |
+
"""Process output and display it appropriately."""
|
41 |
+
if isinstance(output, str):
|
42 |
+
# If output is a string, assume it's an error message and display it as text.
|
43 |
+
return gr.outputs.Textbox()(output)
|
44 |
+
elif isinstance(output, Path):
|
45 |
+
# If output is a Path, assume it's an error file and provide it as a downloadable file.
|
46 |
+
return gr.outputs.File()(str(output))
|
47 |
+
elif isinstance(output, list):
|
48 |
+
# If output is a list, assume it's a list of Paths or URLs and display it as a markdown list.
|
49 |
+
return gr.outputs.Markdown()("\n".join(f"- {o}" for o in output))
|
50 |
+
else:
|
51 |
+
raise TypeError("Unexpected output type")
|
52 |
+
|
53 |
+
gr.Interface(
|
54 |
+
convert_video,
|
55 |
+
inputs=[video_file, quality, aspect_ratio, video_url, api_key, upload],
|
56 |
+
outputs=gr.outputs.Any(),
|
57 |
+
output_processor=process_output,
|
58 |
+
allow_flagging=False,
|
59 |
+
live=False,
|
60 |
+
).launch()
|
61 |
+
|
62 |
|
63 |
def get_aspect_ratio(input_path, aspect_ratio):
|
64 |
"""Returns the aspect ratio of the video, calculating it if necessary."""
|
|
|
84 |
logging.exception("An error occurred while uploading to web3.storage.")
|
85 |
return f"An error occurred while uploading to web3.storage: {response.json()}"
|
86 |
|
87 |
+
def create_master_playlist(output_paths, temp_dir):
|
88 |
+
"""Creates a master playlist .m3u8 file that includes all other .m3u8 files."""
|
89 |
+
master_playlist_path = temp_dir / "master_playlist.m3u8"
|
90 |
+
with open(master_playlist_path, 'w') as f:
|
91 |
+
f.write("#EXTM3U\n")
|
92 |
+
for path in output_paths:
|
93 |
+
f.write(f"#EXT-X-STREAM-INF:BANDWIDTH={1000*1000},RESOLUTION={path.stem.split('_')[-1]}\n")
|
94 |
+
f.write(f"{path.name}\n")
|
95 |
+
return master_playlist_path
|
96 |
+
|
97 |
def convert_video(video_file, quality, aspect_ratio, video_url, api_key, upload):
|
98 |
standard_resolutions = [4320, 2160, 1440, 1080, 720, 480] # 8K, 4K, 2K, Full HD, HD, SD in pixels
|
99 |
|
|
|
121 |
"-vf", f"scale={scale},setsar={aspect_ratio}", "-hls_time", "6",
|
122 |
"-hls_playlist_type", "vod", "-f", "hls", str(output_path)
|
123 |
]
|
124 |
+
|
125 |
try:
|
126 |
+
logging.info("Running command: %s", " ".join(ffmpeg_command))
|
127 |
+
subprocess.run(ffmpeg_command, check=True, timeout=600, stderr=subprocess.PIPE)
|
128 |
except subprocess.CalledProcessError as e:
|
129 |
logging.exception("ffmpeg command failed.")
|
130 |
+
error_file_path = temp_dir / "error.txt"
|
131 |
with open(error_file_path, 'w') as error_file:
|
132 |
+
error_file.write("ffmpeg command failed:\n")
|
|
|
133 |
error_file.write(e.stderr.decode())
|
134 |
return error_file_path
|
|
|
135 |
except subprocess.TimeoutExpired:
|
136 |
logging.exception("ffmpeg command timed out.")
|
137 |
return "ffmpeg command timed out."
|
|
|
147 |
if not output_paths:
|
148 |
return "The video is smaller than the smallest standard resolution."
|
149 |
|
150 |
+
# Create master playlist
|
151 |
+
master_playlist_path = create_master_playlist(output_paths, temp_dir)
|
152 |
+
|
153 |
output_copy_paths = [shutil.copy2(path, tempfile.gettempdir()) for path in output_paths]
|
154 |
+
master_playlist_copy_path = shutil.copy2(master_playlist_path, tempfile.gettempdir())
|
155 |
|
156 |
if upload:
|
157 |
+
return [upload_to_web3_storage(api_key, path) for path in [master_playlist_copy_path] + output_copy_paths]
|
158 |
else:
|
159 |
+
return [master_playlist_copy_path] + output_copy_paths
|
160 |
|
161 |
|
162 |
def main():
|
|
|
168 |
"1.85:1", "2.35:1", "3:1", "360", "9:16", "16:9",
|
169 |
"2:1", "1:2", "9:1"],
|
170 |
label="Aspect Ratio", default="16:9")
|
|
|
|
|
171 |
video_url = gr.inputs.Textbox(label="Video URL")
|
172 |
api_key = gr.inputs.Textbox(label="web3.storage API Key")
|
173 |
upload = gr.inputs.Checkbox(label="Upload to web3.storage", default=False)
|