Spaces:
Paused
Paused
File size: 6,344 Bytes
d60ecdf 8412930 d60ecdf 8412930 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf 8412930 f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf f97ecc6 d60ecdf 8412930 d60ecdf |
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 169 170 171 |
import requests
from urllib.parse import urlparse, quote_plus
import subprocess
from pathlib import Path
from moviepy.editor import VideoFileClip
import streamlit as st
import http.server
import socketserver
import threading
import socket
import boto3
import s3fs
import os
# Define output directory
output_dir = Path.cwd() / "output"
output_dir.mkdir(exist_ok=True)
# Set S3 credentials
AWS_S3_BUCKET = os.getenv("AWS_S3_BUCKET")
AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID")
AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY")
session = boto3.Session(
aws_access_key_id=AWS_ACCESS_KEY_ID,
aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
region_name='us-east-1'
)
s3 = session.client('s3')
fs = s3fs.S3FileSystem(anon=False, client_kwargs={'region_name': 'us-east-1'})
logging.basicConfig(level=logging.INFO)
standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240]
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:
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
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:
# Save the uploaded file to the output directory
input_path = output_dir / video_file.name
with open(input_path, "wb") as f:
f.write(video_file.getbuffer())
return input_path
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 / f"{Path(input_path).stem}_{res}p.m3u8"
return output_path
def create_master_playlist(output_paths, input_filename):
master_playlist_path = output_dir / f"{input_filename}_master_playlist.m3u8"
with open(master_playlist_path, "w") as f:
f.write("#EXTM3U\n")
for path in output_paths:
res = Path(path).stem.split("_")[1]
f.write(f'#EXT-X-STREAM-INF:BANDWIDTH=8000000,RESOLUTION={res}\n')
# read the .m3u8 file and replace relative links with absolute links
with open(path, 'r') as playlist_file:
content = playlist_file.readlines()
content = [line.replace('.ts', f'.ts\n') if line.endswith('.ts\n') else line for line in content]
content = [f"{quote_plus(line.rstrip())}\n" if line.endswith('.ts\n') else line for line in content]
f.writelines(content)
return master_playlist_path
def upload_file_to_s3(local_path, s3_key):
s3 = boto3.client(
"s3",
aws_access_key_id=st.secrets["AWS_ACCESS_KEY_ID"],
aws_secret_access_key=st.secrets["AWS_SECRET_ACCESS_KEY"],
region_name=st.secrets["AWS_REGION"],
)
bucket_name = st.secrets["AWS_S3_BUCKET"]
with open(local_path, "rb") as file:
s3.upload_fileobj(file, bucket_name, s3_key)
return f"https://{bucket_name}.s3.amazonaws.com/{s3_key}"
def convert_video(video_file, quality, aspect_ratio, video_url):
# Ensure either a file or a URL is provided
if not video_file and not video_url:
raise ValueError("Please provide either a video file or a video URL.")
input_path = get_input_path(video_file, video_url)
st.write(f"Input file path: {input_path}") # Added line to print input file path
video = VideoFileClip(str(input_path))
# Get the original height to avoid upscaling
original_height = video.size[1]
output_paths = []
for res in reversed(standard_resolutions):
if res > original_height:
continue
scale = "-1:" + str(res)
output_path = get_output_path(input_path, str(res) + 'p')
# use a lower CRF value for better quality
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, Path(input_path).stem)
output_paths.append(master_playlist_path)
output_links = []
for path in output_paths:
s3_path = f"s3://{AWS_S3_BUCKET}/{Path(input_path).stem}/{Path(path).name}"
upload_file_to_s3(path, s3_path)
output_links.append(f'<a href="https://{AWS_S3_BUCKET}.s3.amazonaws.com/{Path(input_path).stem}/{quote_plus(Path(path).name)}" target="_blank">Download {Path(path).stem}</a>')
# upload ts files to s3
for path in output_dir.glob(f"{Path(input_path).stem}_*p_*.ts"):
s3_path = f"s3://{AWS_S3_BUCKET}/{Path(input_path).stem}/{Path(path).name}"
upload_file_to_s3(path, s3_path)
output_html = "<br>".join(output_links)
return output_html
st.title("NEAR Hub Video Transcoder to m3u8")
st.markdown("Convert video files to m3u8 for VOD streaming in nearhub.club.")
video_file = st.file_uploader("Your video file")
quality = st.slider("Quality (0: Highest Quality - 50: Fastest)", min_value=0, max_value=51, value=23)
aspect_ratio = st.selectbox("Aspect Ratio", ["16:9", "4:3", "1:1", "3:4", "9:16", "1:1", "2:1", "1:2"], index=0)
video_url = st.text_input("Video URL", "")
if st.button("Transcode"):
output_html = convert_video(video_file, quality, aspect_ratio, video_url)
st.write(output_html, unsafe_allow_html=True) |