Jeffgold commited on
Commit
07853df
·
1 Parent(s): a25ec23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +20 -67
app.py CHANGED
@@ -1,55 +1,12 @@
1
  import logging
2
  import shutil
3
- import tempfile
4
- import subprocess
5
  from pathlib import Path
6
  from moviepy.editor import VideoFileClip
7
  import gradio as gr
8
  import requests
9
  from urllib.parse import urlparse
10
- import http.server
11
- import socketserver
12
- import threading
13
  import atexit
14
- import socket
15
-
16
- logging.basicConfig(level=logging.INFO)
17
-
18
- PORT = 8000 # Define PORT here
19
-
20
- def get_available_port(start_port):
21
- while True:
22
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
23
- try:
24
- s.bind(("", start_port))
25
- return start_port
26
- except OSError as e:
27
- if e.errno == 98: # errno 98 means address already in use
28
- start_port += 1 # If address in use, increment port and try again
29
- continue
30
- else:
31
- raise
32
-
33
- temp_dir = Path(tempfile.mkdtemp()) # Create a temporary directory using mkdtemp() instead of TemporaryDirectory()
34
-
35
- class Handler(http.server.SimpleHTTPRequestHandler):
36
- def __init__(self, *args, **kwargs):
37
- super().__init__(*args, directory=str(temp_dir), **kwargs)
38
-
39
- def start_server():
40
- global PORT # Make sure to define PORT as global
41
- PORT = get_available_port(PORT)
42
- with socketserver.TCPServer(("", PORT), Handler) as httpd:
43
- print(f"Serving at port {PORT}")
44
- httpd.serve_forever()
45
-
46
- t = threading.Thread(target=start_server)
47
- t.start()
48
-
49
- # Cleanup function to remove the temporary directory when the script is exited
50
- @atexit.register
51
- def cleanup():
52
- shutil.rmtree(temp_dir)
53
 
54
  logging.basicConfig(level=logging.INFO)
55
 
@@ -60,22 +17,22 @@ def download_file(url, destination):
60
  with open(destination, 'wb') as f:
61
  f.write(response.content)
62
 
63
- def get_input_path(video_file, video_url, temp_dir):
64
  """Returns the path to the video file, downloading it if necessary."""
65
  if video_file is not None:
66
  return Path(video_file.name)
67
  elif video_url:
68
  url_path = urlparse(video_url).path
69
  file_name = Path(url_path).name
70
- destination = temp_dir / file_name
71
  download_file(video_url, destination)
72
  return destination
73
  else:
74
  raise ValueError("No input was provided.")
75
 
76
- def get_output_path(input_path, temp_dir, res):
77
  """Returns the path to the output file, creating it if necessary."""
78
- output_path = temp_dir / (Path(input_path).stem + f"_{res}.m3u8")
79
  return output_path
80
 
81
  def get_aspect_ratio(input_path, aspect_ratio):
@@ -85,9 +42,9 @@ def get_aspect_ratio(input_path, aspect_ratio):
85
  video = VideoFileClip(str(input_path))
86
  return f"{video.size[0]}:{video.size[1]}"
87
 
88
- def create_master_playlist(output_paths, temp_dir):
89
  """Creates a master playlist .m3u8 file that includes all other .m3u8 files."""
90
- master_playlist_path = temp_dir / "master_playlist.m3u8"
91
  with open(master_playlist_path, 'w') as f:
92
  f.write("#EXTM3U\n")
93
  for path in output_paths:
@@ -96,15 +53,13 @@ def create_master_playlist(output_paths, temp_dir):
96
  return master_playlist_path
97
 
98
  def convert_video(video_file, quality, aspect_ratio, video_url):
99
- # Use the already-created temp_dir instead of creating a new one
100
- # temp_dir = Path(tempfile.mkdtemp())
101
- input_path = get_input_path(video_file, video_url, temp_dir)
102
  aspect_ratio = get_aspect_ratio(input_path, aspect_ratio)
103
 
104
  video = VideoFileClip(str(input_path))
105
  original_height = video.size[1]
106
 
107
- output_paths = [] # Define output_paths as an empty list
108
 
109
  for res in standard_resolutions:
110
  # Skip if resolution is higher than original
@@ -112,28 +67,27 @@ def convert_video(video_file, quality, aspect_ratio, video_url):
112
  continue
113
 
114
  scale = "-1:" + str(res) # we scale the height to res and keep aspect ratio
115
- output_path = get_output_path(input_path, temp_dir, str(res) + 'p') # pass the resolution to create a unique output file
116
 
117
  ffmpeg_command = [
118
  "ffmpeg", "-i", str(input_path), "-c:v", "libx264", "-crf", str(quality),
119
  "-vf", f"scale={scale}:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2",
120
  "-hls_time", "10", "-hls_playlist_type", "vod", "-hls_segment_filename",
121
- str(temp_dir / f"{output_path.stem}_%03d.ts"), str(output_path)
122
  ]
123
 
124
  logging.info("Running ffmpeg command: " + ' '.join(ffmpeg_command))
125
  subprocess.run(ffmpeg_command, check=True)
126
 
127
- output_paths.append(output_path) # Append each completed output file to the output_paths list
128
 
129
- master_playlist_path = create_master_playlist(output_paths, temp_dir)
130
  output_paths.append(master_playlist_path)
131
 
132
- # Convert Path objects to URLs before returning
133
- return format_output([{'name': path.stem, 'url': f"http://localhost:{PORT}/{path.name}"} for path in output_paths])
134
 
135
 
136
- video_file = gr.File(label="Video File")
137
  quality = gr.inputs.Dropdown(
138
  choices=["18", "23", "27", "28", "32"],
139
  default="27",
@@ -145,23 +99,22 @@ aspect_ratio = gr.inputs.Dropdown(
145
  label="Aspect ratio (width:height)"
146
  )
147
  standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240, 144] # 8K, 4K, 2K, Full HD, HD, SD in pixels
148
- video_url = gr.Textbox(label="Or enter video URL")
149
 
150
  def format_output(output):
151
  html = ""
152
  for file in output:
153
- html += f'<p><a href="{file["url"]}">{file["name"]}</a></p>'
154
  return html
155
 
156
  interface = gr.Interface(
157
  fn=convert_video,
158
  inputs=[video_file, quality, aspect_ratio, video_url],
159
- outputs=gr.outputs.HTML(label="Download Links"),
160
  title="Video Converter",
161
  description="A simple video converter app",
162
  allow_flagging=False,
 
 
163
  )
164
  interface.launch()
165
-
166
-
167
-
 
1
  import logging
2
  import shutil
 
 
3
  from pathlib import Path
4
  from moviepy.editor import VideoFileClip
5
  import gradio as gr
6
  import requests
7
  from urllib.parse import urlparse
8
+ import subprocess
 
 
9
  import atexit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  logging.basicConfig(level=logging.INFO)
12
 
 
17
  with open(destination, 'wb') as f:
18
  f.write(response.content)
19
 
20
+ def get_input_path(video_file, video_url):
21
  """Returns the path to the video file, downloading it if necessary."""
22
  if video_file is not None:
23
  return Path(video_file.name)
24
  elif video_url:
25
  url_path = urlparse(video_url).path
26
  file_name = Path(url_path).name
27
+ destination = Path.cwd() / file_name
28
  download_file(video_url, destination)
29
  return destination
30
  else:
31
  raise ValueError("No input was provided.")
32
 
33
+ def get_output_path(input_path, res):
34
  """Returns the path to the output file, creating it if necessary."""
35
+ output_path = Path.cwd() / (Path(input_path).stem + f"_{res}.m3u8")
36
  return output_path
37
 
38
  def get_aspect_ratio(input_path, aspect_ratio):
 
42
  video = VideoFileClip(str(input_path))
43
  return f"{video.size[0]}:{video.size[1]}"
44
 
45
+ def create_master_playlist(output_paths):
46
  """Creates a master playlist .m3u8 file that includes all other .m3u8 files."""
47
+ master_playlist_path = Path.cwd() / "master_playlist.m3u8"
48
  with open(master_playlist_path, 'w') as f:
49
  f.write("#EXTM3U\n")
50
  for path in output_paths:
 
53
  return master_playlist_path
54
 
55
  def convert_video(video_file, quality, aspect_ratio, video_url):
56
+ input_path = get_input_path(video_file, video_url)
 
 
57
  aspect_ratio = get_aspect_ratio(input_path, aspect_ratio)
58
 
59
  video = VideoFileClip(str(input_path))
60
  original_height = video.size[1]
61
 
62
+ output_paths = []
63
 
64
  for res in standard_resolutions:
65
  # Skip if resolution is higher than original
 
67
  continue
68
 
69
  scale = "-1:" + str(res) # we scale the height to res and keep aspect ratio
70
+ output_path = get_output_path(input_path, str(res) + 'p') # pass the resolution to create a unique output file
71
 
72
  ffmpeg_command = [
73
  "ffmpeg", "-i", str(input_path), "-c:v", "libx264", "-crf", str(quality),
74
  "-vf", f"scale={scale}:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2",
75
  "-hls_time", "10", "-hls_playlist_type", "vod", "-hls_segment_filename",
76
+ str(Path.cwd() / f"{output_path.stem}_%03d.ts"), str(output_path)
77
  ]
78
 
79
  logging.info("Running ffmpeg command: " + ' '.join(ffmpeg_command))
80
  subprocess.run(ffmpeg_command, check=True)
81
 
82
+ output_paths.append(output_path)
83
 
84
+ master_playlist_path = create_master_playlist(output_paths)
85
  output_paths.append(master_playlist_path)
86
 
87
+ return [{'name': path.stem, 'url': f"{path.name}"} for path in output_paths]
 
88
 
89
 
90
+ video_file = gr.inputs.File(label="Video File")
91
  quality = gr.inputs.Dropdown(
92
  choices=["18", "23", "27", "28", "32"],
93
  default="27",
 
99
  label="Aspect ratio (width:height)"
100
  )
101
  standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240, 144] # 8K, 4K, 2K, Full HD, HD, SD in pixels
102
+ video_url = gr.inputs.Textbox(label="Or enter video URL")
103
 
104
  def format_output(output):
105
  html = ""
106
  for file in output:
107
+ html += f'<p><a href="{file["url"]}" target="_blank">{file["name"]}</a></p>'
108
  return html
109
 
110
  interface = gr.Interface(
111
  fn=convert_video,
112
  inputs=[video_file, quality, aspect_ratio, video_url],
113
+ outputs=gr.outputs.HTML(label="Download Links", type="html"),
114
  title="Video Converter",
115
  description="A simple video converter app",
116
  allow_flagging=False,
117
+ server_name="0.0.0.0",
118
+ server_port=7860,
119
  )
120
  interface.launch()