Spaces:
Paused
Paused
File size: 5,833 Bytes
c16a803 5296733 c16a803 40446f2 e4ed31e 6c154f8 c16a803 40446f2 6c154f8 c16a803 6c154f8 79683ca 6c154f8 79683ca c047e75 e4ed31e cbd85fc 6c154f8 3c753ee 6c154f8 c16a803 6c154f8 79683ca 6c154f8 6f1f7b0 c358ea4 a8cf125 c358ea4 a8cf125 b6be762 c358ea4 5a36eaa c16a803 5a36eaa c16a803 6f1f7b0 0212a08 e280197 5a36eaa bd750f5 5a36eaa e280197 ffe2496 c358ea4 15d3f13 6c154f8 d10be9a 95bc252 d10be9a 6c154f8 5a36eaa d10be9a b7e494d 15d3f13 95bc252 d10be9a 95bc252 9412aac b7e494d 6c154f8 c358ea4 |
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 |
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
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):
"""Returns the path to the output file, creating it if necessary."""
output_path = temp_dir / (Path(input_path).stem + ".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 upload_to_web3_storage(api_key, path):
"""Uploads a file to web3.storage using the HTTP API."""
headers = {"Authorization": f"Bearer {api_key}"}
with open(path, 'rb') as f:
response = requests.post(
"https://api.web3.storage/upload",
headers=headers,
data=f,
)
response.raise_for_status() # Raises an exception if the request failed
try:
cid = response.json()["value"]["cid"]
return f"https://dweb.link/ipfs/{cid}"
except KeyError:
logging.exception("An error occurred while uploading to web3.storage.")
return f"An error occurred while uploading to web3.storage: {response.json()}"
def convert_video(video_file, quality, aspect_ratio, video_url, api_key, upload, resolution):
with tempfile.TemporaryDirectory() as temp_dir:
temp_dir = Path(temp_dir)
input_path = get_input_path(video_file, video_url, temp_dir)
aspect_ratio = get_aspect_ratio(input_path, aspect_ratio)
# Check if resolution is a list, if not convert it to a list
resolution = [resolution] if not isinstance(resolution, list) else resolution
output_path = None # Define output_path before the loop
for res in resolution:
# Skip if res is boolean
if isinstance(res, bool):
continue
scale = "-1:" + str(res.replace("p", "")) # we convert '1080p' to '-1:1080'
output_path = get_output_path(input_path, temp_dir, res) # 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},setsar={aspect_ratio}", "-hls_time", "6",
"-hls_playlist_type", "vod", "-f", "hls", str(output_path)
]
try:
logging.info("Running command: %s", " ".join(ffmpeg_command))
subprocess.run(ffmpeg_command, check=True, timeout=600)
except subprocess.CalledProcessError:
logging.exception("ffmpeg command failed.")
error_file_path = tempfile.gettempdir() + "/error.txt"
with open(error_file_path, 'w') as error_file:
error_file.write("ffmpeg command failed.")
return error_file_path
except subprocess.TimeoutExpired:
logging.exception("ffmpeg command timed out.")
return "ffmpeg command timed out."
except FileNotFoundError:
logging.exception("ffmpeg is not installed.")
return "ffmpeg is not installed."
except Exception as e:
logging.exception("An error occurred.")
return f"An error occurred: {str(e)}"
# We need to modify this part if you want to return all converted videos
# Here we only return the last converted video
# Check if output_path is None after the loop
if output_path is None:
return "No resolution was selected."
output_copy_path = shutil.copy2(output_path, tempfile.gettempdir())
if upload:
return upload_to_web3_storage(api_key, output_copy_path)
else:
return output_copy_path
def main():
video_file = gr.inputs.File(label="Video File")
quality = gr.inputs.Dropdown(
choices=["18", "23", "27", "28", "32"], label="Quality", default="27")
aspect_ratio = gr.inputs.Dropdown(
choices=[None, "1:1", "4:3", "3:2", "5:4", "16:9", "21:9",
"1.85:1", "2.35:1", "3:1", "360", "9:16", "16:9",
"2:1", "1:2", "9:1"],
label="Aspect Ratio", default=None)
resolution = gr.components.Dropdown(
choices=["480p", "720p", "1080p", "1440p", "2160p", "4320p"], label="Resolution", multiple=True, default=["1080p"])
video_url = gr.inputs.Textbox(label="Video URL")
api_key = gr.inputs.Textbox(label="web3.storage API Key")
upload = gr.inputs.Checkbox(label="Upload to web3.storage", default=False)
gr.Interface(
convert_video,
inputs=[video_file, quality, aspect_ratio, resolution, video_url, api_key, upload],
outputs=gr.outputs.File(label="Download File"),
allow_flagging=False,
live=False,
).launch()
if __name__ == "__main__":
main()
|