import logging
import requests
import gradio
from urllib.parse import urlparse
import subprocess
from pathlib import Path
from moviepy.editor import VideoFileClip
import gradio as gr
from gradio import components
import http.server
import socketserver
import threading
import socket
# Define output directory
output_dir = Path.cwd() / "output"
output_dir.mkdir(exist_ok=True)
logging.basicConfig(level=logging.INFO)
standard_resolutions = [240, 360, 480, 720, 1080, 1440, 2160, 4320]
quality_mapping = {
"Low": 35,
"Medium": 23,
"High": 18,
}
def start_http_server(port=8000):
handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", port), handler)
logging.info(f"Serving at port {port}")
thread = threading.Thread(target=httpd.serve_forever)
thread.start()
def get_ip_address():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
def get_public_ip_address():
response = requests.get('https://httpbin.org/ip')
return response.json()['origin']
def download_file(url, 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):
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 = output_dir / file_name
download_file(video_url, destination)
return destination
else:
raise ValueError("No input was provided.")
def get_output_path(input_path, res):
output_path = output_dir / (Path(input_path).stem + f"_{res}p.m3u8")
return output_path
def get_aspect_ratio(input_path, aspect_ratio):
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):
master_playlist_path = output_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):
input_path = get_input_path(video_file, video_url)
aspect_ratio = get_aspect_ratio(input_path, aspect_ratio)
video = VideoFileClip(str(input_path))
original_height = video.size[1]
output_paths = []
for res in standard_resolutions:
if res > original_height:
continue
scale = "-1:" + str(res)
output_path = get_output_path(input_path, str(res) + 'p')
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(output_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)
master_playlist_path = create_master_playlist(output_paths)
output_paths.append(master_playlist_path)
# Get server IP and generate output links
server_ip = get_ip_address() # or get_public_ip_address() if you need the public IP
output_links = []
for path in output_paths:
# Replace 'your_server_ip' with server_ip
output_links.append(f'Download {Path(path).stem}')
output_html = "
".join(output_links)
return output_html
# Change "video" to "file"
video_file = gradio.inputs.File(label="Your video file")
quality = gradio.inputs.Slider(minimum=1, maximum=50, default=25, label="Quality (1:Speed - 50:Quality)")
aspect_ratio = gradio.inputs.Dropdown(["16:9", "4:3", "1:1", "3:4", "9:16", "1:1", "2:1", "1:2"], label="Aspect Ratio", default="16:9")
video_url = gradio.inputs.Textbox(lines=1, placeholder="or paste video url here", label="Video URL")
# Update the aspect ratio selection to include the comprehensive list
# aspect_ratio = gr.inputs.Dropdown(choices=aspect_ratios, label="Aspect Ratio", default="16:9")
interface = gradio.Interface(
fn=convert_video,
inputs=[video_file, quality, aspect_ratio, video_url],
outputs=gradio.outputs.HTML(label="Download Links"),
title="NEAR Hub Video Transcoder to m3u8",
description="convert video files to m3u8 for VOD streaming",
allow_flagging=False
)
start_http_server()
interface.launch(server_name="0.0.0.0", server_port=7860)