Jeffgold commited on
Commit
30f78b0
·
1 Parent(s): d3e2a95

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -10
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
- result = subprocess.run(ffmpeg_command, check=True, timeout=600, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
94
  except subprocess.CalledProcessError as e:
95
  logging.exception("ffmpeg command failed.")
96
- error_file_path = tempfile.gettempdir() + "/error.txt"
97
  with open(error_file_path, 'w') as error_file:
98
- error_file.write("ffmpeg command failed. Output was:\n\n")
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)