Jeffgold commited on
Commit
d51b3b7
·
1 Parent(s): 666b7f5

Create appBackup.py

Browse files
Files changed (1) hide show
  1. appBackup.py +148 -0
appBackup.py ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ import shutil
3
+ from pathlib import Path
4
+ from moviepy.editor import VideoFileClip
5
+ import gradio as gr
6
+ import requests
7
+ from urllib.parse import urlparse
8
+ import subprocess
9
+ import atexit
10
+ from flask import Flask, send_from_directory
11
+ from threading import Thread
12
+
13
+ # Initialize a Flask application
14
+ app = Flask(__name__)
15
+
16
+ @app.route('/files/<path:path>')
17
+ def serve_file(path):
18
+ return send_from_directory(Path.cwd(), path)
19
+
20
+ # Start the Flask server in a new thread
21
+ Thread(target=app.run, kwargs={'host': '0.0.0.0', 'port': 5000}).start()
22
+
23
+ logging.basicConfig(level=logging.INFO)
24
+
25
+ def download_file(url, destination):
26
+ """Downloads a file from a url to a destination."""
27
+ response = requests.get(url)
28
+ response.raise_for_status()
29
+ with open(destination, 'wb') as f:
30
+ f.write(response.content)
31
+
32
+ def get_input_path(video_file, video_url):
33
+ """Returns the path to the video file, downloading it if necessary."""
34
+ if video_file is not None:
35
+ return Path(video_file.name)
36
+ elif video_url:
37
+ url_path = urlparse(video_url).path
38
+ file_name = Path(url_path).name
39
+ destination = Path.cwd() / file_name
40
+ download_file(video_url, destination)
41
+ return destination
42
+ else:
43
+ raise ValueError("No input was provided.")
44
+
45
+ def get_output_path(input_path, res):
46
+ """Returns the path to the output file, creating it if necessary."""
47
+ output_path = Path.cwd() / (Path(input_path).stem + f"_{res}.m3u8")
48
+ return output_path
49
+
50
+ def get_aspect_ratio(input_path, aspect_ratio):
51
+ """Returns the aspect ratio of the video, calculating it if necessary."""
52
+ if aspect_ratio is not None:
53
+ return aspect_ratio
54
+ video = VideoFileClip(str(input_path))
55
+ return f"{video.size[0]}:{video.size[1]}"
56
+
57
+ def create_master_playlist(output_paths):
58
+ """Creates a master playlist .m3u8 file that includes all other .m3u8 files."""
59
+ master_playlist_path = Path.cwd() / "master_playlist.m3u8"
60
+ with open(master_playlist_path, 'w') as f:
61
+ f.write("#EXTM3U\n")
62
+ for path in output_paths:
63
+ f.write(f"#EXT-X-STREAM-INF:BANDWIDTH={1000*1000},RESOLUTION={path.stem.split('_')[-1]}\n")
64
+ f.write(f"{path.name}\n")
65
+ return master_playlist_path # make sure this is a single Path object
66
+
67
+
68
+ def convert_video(video_file, quality, aspect_ratio, video_url):
69
+ input_path = get_input_path(video_file, video_url)
70
+ aspect_ratio = get_aspect_ratio(input_path, aspect_ratio)
71
+
72
+ video = VideoFileClip(str(input_path))
73
+ original_height = video.size[1]
74
+
75
+ output_paths = []
76
+
77
+ for res in standard_resolutions:
78
+ # Skip if resolution is higher than original
79
+ if res > original_height:
80
+ continue
81
+
82
+ scale = "-1:" + str(res) # we scale the height to res and keep aspect ratio
83
+ output_path = get_output_path(input_path, str(res) + 'p') # pass the resolution to create a unique output file
84
+
85
+ ffmpeg_command = [
86
+ "ffmpeg", "-i", str(input_path), "-c:v", "libx264", "-crf", str(quality),
87
+ "-vf", f"scale={scale}:force_original_aspect_ratio=decrease,pad=ceil(iw/2)*2:ceil(ih/2)*2",
88
+ "-hls_time", "10", "-hls_playlist_type", "vod", "-hls_segment_filename",
89
+ str(Path.cwd() / f"{output_path.stem}_%03d.ts"), str(output_path)
90
+ ]
91
+
92
+ logging.info("Running ffmpeg command: " + ' '.join(ffmpeg_command))
93
+ subprocess.run(ffmpeg_command, check=True)
94
+
95
+ output_paths.append(output_path)
96
+
97
+ master_playlist_path = create_master_playlist(output_paths)
98
+ output_paths.append(master_playlist_path)
99
+
100
+ html_components = []
101
+
102
+ for path in output_paths:
103
+ # Create a video player and a download link for each video file
104
+ if path.suffix in ['.mp4', '.webm', '.ogg']:
105
+ video_path = f"http://localhost:5000/files/{path.name}"
106
+ video_component = f"<video width='320' height='240' controls><source src='{video_path}' type='video/{path.suffix.lstrip('.')}'>Your browser does not support the video tag.</video>"
107
+ download_link = f"<p><a href='{video_path}' download>Download this video</a></p>"
108
+ html_components.append(f"{video_component}{download_link}")
109
+
110
+ return html_components, # add more return values as needed
111
+
112
+ outputs = [
113
+ gr.outputs.HTML(label="Video Players"),
114
+ # add more outputs as needed
115
+ ]
116
+
117
+
118
+ video_file = gr.inputs.File(label="Video File")
119
+ quality = gr.inputs.Dropdown(
120
+ choices=["18", "23", "27", "28", "32"],
121
+ default="27",
122
+ label="Quality"
123
+ )
124
+ aspect_ratio = gr.inputs.Dropdown(
125
+ 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"],
126
+ default="16:9",
127
+ label="Aspect ratio (width:height)"
128
+ )
129
+ standard_resolutions = [4320, 2160, 1440, 1080, 720, 480, 360, 240, 144] # 8K, 4K, 2K, Full HD, HD, SD in pixels
130
+ video_url = gr.inputs.Textbox(label="Or enter video URL")
131
+
132
+ outputs = [
133
+ gr.outputs.HTML(label="Download Links"),
134
+ gr.outputs.Video(label="Video Player"),
135
+ gr.outputs.Textbox(label="Text Files", type="text")
136
+ ]
137
+
138
+ interface = gr.Interface(
139
+ fn=convert_video,
140
+ inputs=[video_file, quality, aspect_ratio, video_url],
141
+ outputs=outputs,
142
+ title="Video Converter",
143
+ description="A simple video converter app",
144
+ allow_flagging=False,
145
+ server_name="0.0.0.0",
146
+ server_port=7860,
147
+ )
148
+ interface.launch()