Jeffgold commited on
Commit
1229389
·
1 Parent(s): 4bc9886

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +23 -112
app.py CHANGED
@@ -7,8 +7,6 @@ from moviepy.editor import VideoFileClip
7
  import gradio as gr
8
  import requests
9
  from urllib.parse import urlparse
10
- from ftplib import FTP
11
- import paramiko
12
 
13
  logging.basicConfig(level=logging.INFO)
14
 
@@ -32,24 +30,6 @@ def get_input_path(video_file, video_url, temp_dir):
32
  else:
33
  raise ValueError("No input was provided.")
34
 
35
- def upload_to_ftp(server, port, username, password, source_file, destination_file):
36
- """Uploads a file to an FTP server."""
37
- with FTP(server, username, password) as ftp:
38
- ftp.connect(server, int(port)) # add this line to specify the port
39
- with open(source_file, 'rb') as f:
40
- ftp.storbinary(f'STOR {destination_file}', f)
41
-
42
- def upload_to_sftp(server, port, username, password, source_file, destination_file):
43
- """Uploads a file to an SFTP server."""
44
- transport = paramiko.Transport((server, int(port)))
45
- transport.connect(username=username, password=password)
46
-
47
- sftp = paramiko.SFTPClient.from_transport(transport)
48
- sftp.put(source_file, destination_file)
49
-
50
- sftp.close()
51
- transport.close()
52
-
53
  def get_output_path(input_path, temp_dir, res):
54
  """Returns the path to the output file, creating it if necessary."""
55
  output_path = temp_dir / (Path(input_path).stem + f"_{res}.m3u8")
@@ -72,7 +52,7 @@ def create_master_playlist(output_paths, temp_dir):
72
  f.write(f"{path.name}\n")
73
  return master_playlist_path
74
 
75
- def convert_video(video_file, quality, aspect_ratio, video_url, ftp_server, ftp_port, ftp_username, ftp_password, ftp_path, upload):
76
  standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240, 144] # 8K, 4K, 2K, Full HD, HD, SD in pixels
77
 
78
  with tempfile.TemporaryDirectory() as temp_dir:
@@ -96,101 +76,32 @@ def convert_video(video_file, quality, aspect_ratio, video_url, ftp_server, ftp_
96
 
97
  ffmpeg_command = [
98
  "ffmpeg", "-i", str(input_path), "-c:v", "libx264", "-crf", str(quality),
99
- "-vf", f"scale={scale}:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2,setsar={aspect_ratio}",
100
- "-hls_time", "6",
101
- "-hls_playlist_type", "vod", "-f", "hls", str(output_path)
102
  ]
103
 
104
- try:
105
- result = subprocess.run(ffmpeg_command, check=True, timeout=600, capture_output=True, text=True)
106
- except subprocess.CalledProcessError as e:
107
- logging.error("ffmpeg command failed with the following error:\n%s", e.stderr)
108
- error_file_path = tempfile.gettempdir() + "/error.txt"
109
- with open(error_file_path, 'w') as error_file:
110
- error_file.write("ffmpeg command failed with the following error:\n" + e.stderr)
111
- return error_file_path
112
-
113
- except subprocess.TimeoutExpired:
114
- logging.exception("ffmpeg command timed out.")
115
- return "ffmpeg command timed out."
116
- except FileNotFoundError:
117
- logging.exception("ffmpeg is not installed.")
118
- return "ffmpeg is not installed."
119
- except Exception as e:
120
- logging.exception("An error occurred.")
121
- return f"An error occurred: {str(e)}"
122
-
123
- output_paths.append(output_path) # Append the output_path to output_paths
124
-
125
- if upload:
126
- ftp_files = []
127
- for path in [master_playlist_copy_path] + output_copy_paths:
128
- source_file = path # This should be the full local path of the file
129
- destination_file = ftp_path + "/" + path.name # This should be the desired remote path of the file
130
-
131
- # Distinguish between FTP and SFTP based on the port number
132
- if ftp_port == 22:
133
- upload_to_sftp(ftp_server, ftp_port, ftp_username, ftp_password, source_file, destination_file)
134
- else:
135
- upload_to_ftp(ftp_server, ftp_port, ftp_username, ftp_password, source_file, destination_file)
136
-
137
- ftp_files.append(destination_file)
138
- return ftp_files
139
- else:
140
- return [master_playlist_copy_path] + output_copy_paths
141
-
142
- if not output_paths:
143
- return "The video is smaller than the smallest standard resolution."
144
-
145
- # Create master playlist
146
  master_playlist_path = create_master_playlist(output_paths, temp_dir)
 
147
 
148
- output_copy_paths = [shutil.copy2(path, tempfile.gettempdir()) for path in output_paths]
149
- master_playlist_copy_path = shutil.copy2(master_playlist_path, tempfile.gettempdir())
150
 
151
- return [master_playlist_copy_path] + output_copy_paths
 
 
 
152
 
 
 
 
 
 
 
 
153
 
154
- def process_output(output):
155
- """Process output and display it appropriately."""
156
- if isinstance(output, str):
157
- # If output is a string, assume it's an error message and display it as text.
158
- return output
159
- elif isinstance(output, Path):
160
- # If output is a Path, assume it's an error file and provide it as a downloadable file.
161
- return str(output)
162
- elif isinstance(output, list):
163
- # If output is a list, assume it's a list of Paths or URLs and display it as a markdown list.
164
- return "\n".join(f"- {o}" for o in output)
165
- else:
166
- raise TypeError("Unexpected output type")
167
-
168
- def main():
169
- video_file = gr.inputs.File(label="Video File")
170
- quality = gr.inputs.Dropdown(
171
- choices=["18", "23", "27", "28", "32"], label="Quality", default="27")
172
- aspect_ratio = gr.inputs.Dropdown(
173
- choices=["16:9", "1:1", "4:3", "3:2", "5:4", "21:9",
174
- "1.85:1", "2.35:1", "3:1", "360", "9:16", "16:9",
175
- "2:1", "1:2", "9:1"],
176
- label="Aspect Ratio", default="16:9")
177
- video_url = gr.inputs.Textbox(label="Video URL")
178
-
179
- ftp_server = gr.inputs.Textbox(label="FTP Server")
180
- ftp_port = gr.inputs.Textbox(label="FTP Port", placeholder="21")
181
- ftp_username = gr.inputs.Textbox(label="FTP Username")
182
- ftp_password = gr.inputs.Textbox(label="FTP Password", type="text")
183
- ftp_path = gr.inputs.Textbox(label="FTP Path")
184
- upload = gr.inputs.Checkbox(label="Upload to FTP server", default=False)
185
-
186
- gr.Interface(
187
- convert_video,
188
- inputs=[video_file, quality, aspect_ratio, video_url, ftp_server, ftp_port, ftp_username, ftp_password, ftp_path, upload],
189
- outputs=gr.outputs.Textbox(),
190
- output_processor=process_output,
191
- allow_flagging=False,
192
- live=False,
193
- ).launch()
194
-
195
- if __name__ == "__main__":
196
- main()
 
7
  import gradio as gr
8
  import requests
9
  from urllib.parse import urlparse
 
 
10
 
11
  logging.basicConfig(level=logging.INFO)
12
 
 
30
  else:
31
  raise ValueError("No input was provided.")
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  def get_output_path(input_path, temp_dir, res):
34
  """Returns the path to the output file, creating it if necessary."""
35
  output_path = temp_dir / (Path(input_path).stem + f"_{res}.m3u8")
 
52
  f.write(f"{path.name}\n")
53
  return master_playlist_path
54
 
55
+ def convert_video(video_file, quality, aspect_ratio, video_url):
56
  standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240, 144] # 8K, 4K, 2K, Full HD, HD, SD in pixels
57
 
58
  with tempfile.TemporaryDirectory() as temp_dir:
 
76
 
77
  ffmpeg_command = [
78
  "ffmpeg", "-i", str(input_path), "-c:v", "libx264", "-crf", str(quality),
79
+ "-vf", f"scale={scale}:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2",
80
+ "-hls_time", "10", "-hls_playlist_type", "vod", "-hls_segment_filename",
81
+ str(temp_dir / f"{output_path.stem}_%03d.ts"), str(output_path)
82
  ]
83
 
84
+ logging.info("Running ffmpeg command: " + ' '.join(ffmpeg_command))
85
+ subprocess.run(ffmpeg_command, check=True)
86
+
87
+ output_paths.append(output_path) # Append each completed output file to the output_paths list
88
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  master_playlist_path = create_master_playlist(output_paths, temp_dir)
90
+ output_paths.append(master_playlist_path)
91
 
92
+ return output_paths # Return the list of completed output files
 
93
 
94
+ video_file = gr.inputs.File(label="Upload video file")
95
+ quality = gr.inputs.Slider(18, 28, 1, 23, label="Video quality (18-28, lower is better)")
96
+ aspect_ratio = gr.inputs.Textbox("16:9", label="Aspect ratio (width:height)")
97
+ video_url = gr.inputs.Textbox(label="Or enter video URL")
98
 
99
+ iface = gr.Interface(
100
+ convert_video,
101
+ [video_file, quality, aspect_ratio, video_url],
102
+ gr.outputs.File(label="Download video file(s)"),
103
+ title="Video Transcoder",
104
+ description="Transcodes a video file or URL to multiple resolutions for adaptive streaming. Higher quality values reduce the video bitrate."
105
+ )
106
 
107
+ iface.launch()