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