spmoisa548/sama1
14.2k
1import os
2try:
3 from PyQt5 import QtCore, QtGui, QtWidgets
4except:
5 os.system("pip install PyQt5")
6 os.system("pip install DateTime")
7 os.system("pip install requests")
8from PyQt5 import QtCore, QtGui, QtWidgets
9import sys
10import subprocess
11import threading
12from datetime import datetime
13# from api import API
14import base64
15import requests
16import time
17import json
18
19now = datetime.now().strftime("%Y%m%d%H%M%S")
20
21class Ui_Tool(QtCore.QObject):
22 console_signal = QtCore.pyqtSignal(str)
23 def setupUi(self, Tool):
24 Tool.setObjectName("Tool")
25 Tool.resize(900, 500)
26 Tool.setMaximumSize(QtCore.QSize(900, 500))
27 font = QtGui.QFont()
28 font.setFamily("Times New Roman")
29 font.setPointSize(10)
30 Tool.setFont(font)
31 self.centralwidget = QtWidgets.QWidget(parent=Tool)
32 self.centralwidget.setObjectName("centralwidget")
33 self.by = QtWidgets.QLabel(parent=self.centralwidget)
34 self.by.setGeometry(QtCore.QRect(740, 460, 131, 21))
35 self.by.setObjectName("by")
36 self.start_hls = QtWidgets.QPushButton(parent=self.centralwidget)
37 self.start_hls.setGeometry(QtCore.QRect(470, 340, 91, 41))
38 font = QtGui.QFont()
39 font.setFamily("Times New Roman")
40 font.setPointSize(10)
41 self.start_hls.setFont(font)
42 self.start_hls.setObjectName("start_hls")
43 self.input_file = QtWidgets.QToolButton(parent=self.centralwidget)
44 self.input_file.setGeometry(QtCore.QRect(470, 150, 91, 41))
45 self.input_file.setObjectName("input_file")
46 self.output_file = QtWidgets.QToolButton(parent=self.centralwidget)
47 self.output_file.setGeometry(QtCore.QRect(470, 210, 91, 41))
48 self.output_file.setObjectName("output_file")
49 self.console_output = QtWidgets.QPlainTextEdit(parent=self.centralwidget)
50 self.console_output.setGeometry(QtCore.QRect(20, 20, 391, 461))
51 self.console_output.setObjectName("console_output")
52 self.console_output.setReadOnly(True)
53 self.input_path_file = QtWidgets.QLineEdit(parent=self.centralwidget)
54 self.input_path_file.setGeometry(QtCore.QRect(580, 150, 151, 41))
55 font = QtGui.QFont()
56 font.setFamily("Times New Roman")
57 font.setPointSize(7)
58 self.input_path_file.setFont(font)
59 self.input_path_file.setObjectName("input_path_file")
60 self.output_path_file = QtWidgets.QLineEdit(parent=self.centralwidget)
61 self.output_path_file.setGeometry(QtCore.QRect(580, 210, 151, 41))
62 font = QtGui.QFont()
63 font.setFamily("Times New Roman")
64 font.setPointSize(7)
65 self.output_path_file.setFont(font)
66 self.output_path_file.setObjectName("output_path_file")
67 self.start_upload = QtWidgets.QPushButton(parent=self.centralwidget)
68 self.start_upload.setGeometry(QtCore.QRect(470, 410, 91, 41))
69 font = QtGui.QFont()
70 font.setFamily("Times New Roman")
71 font.setPointSize(10)
72 self.start_upload.setFont(font)
73 self.start_upload.setObjectName("start_upload")
74 self.api = QtWidgets.QComboBox(parent=self.centralwidget)
75 self.api.setGeometry(QtCore.QRect(580, 280, 131, 41))
76 self.api.setObjectName("api")
77 self.api.addItem("")
78 self.api.addItem("")
79 self.input_cookie = QtWidgets.QToolButton(parent=self.centralwidget)
80 self.input_cookie.setGeometry(QtCore.QRect(470, 90, 91, 41))
81 self.input_cookie.setObjectName("input_cookie")
82 self.input_path_cookie = QtWidgets.QLineEdit(parent=self.centralwidget)
83 self.input_path_cookie.setGeometry(QtCore.QRect(580, 90, 291, 41))
84 self.input_path_cookie.setObjectName("input_path_cookie")
85 self.input_key = QtWidgets.QLineEdit(parent=self.centralwidget)
86 self.input_key.setGeometry(QtCore.QRect(580, 30, 291, 41))
87 self.input_key.setObjectName("input_key")
88 self.label = QtWidgets.QLabel(parent=self.centralwidget)
89 self.label.setGeometry(QtCore.QRect(500, 30, 31, 41))
90 self.label.setObjectName("label")
91 self.time = QtWidgets.QSpinBox(parent=self.centralwidget)
92 self.time.setGeometry(QtCore.QRect(470, 280, 91, 41))
93 self.time.setMinimum(0)
94 self.time.setObjectName("time")
95 Tool.setCentralWidget(self.centralwidget)
96
97 self.retranslateUi(Tool)
98 self.connect_signals()
99 QtCore.QMetaObject.connectSlotsByName(Tool)
100
101 def retranslateUi(self, Tool):
102 _translate = QtCore.QCoreApplication.translate
103 Tool.setWindowTitle(_translate("Tool", "Tool V1.0.0"))
104 self.by.setText(_translate("Tool", "telegram: pqc2304"))
105 self.start_hls.setText(_translate("Tool", "Start HLS"))
106 self.input_file.setText(_translate("Tool", "Input file"))
107 self.output_file.setText(_translate("Tool", "Output file"))
108 self.start_upload.setText(_translate("Tool", "Start Upload"))
109 self.api.setItemText(0, _translate("Tool", "TikTok V1"))
110 self.api.setItemText(1, _translate("Tool", "Google V1"))
111 self.input_cookie.setText(_translate("Tool", "Cookie"))
112 self.label.setText(_translate("Tool", "Key"))
113
114 def connect_signals(self):
115 """Connect button clicks and signals"""
116 self.input_file.clicked.connect(self.select_input_file)
117 self.output_file.clicked.connect(self.select_output_folder)
118 self.start_hls.clicked.connect(self.start_hls_conversion)
119 self.start_upload.clicked.connect(self.start_upload_process)
120 self.input_cookie.clicked.connect(self.select_input_cookie)
121 self.console_signal.connect(self.update_console)
122
123 @QtCore.pyqtSlot(str)
124 def update_console(self, message):
125 self.console_output.appendPlainText(message)
126
127 def log_to_console(self, message):
128 self.console_signal.emit(f"{message}")
129
130 def select_input_cookie(self):
131 file_path, _ = QtWidgets.QFileDialog.getOpenFileName(
132 None, "Select File Cookie", "",
133 "Cookie Files (*.txt);;All Files (*)"
134 )
135 if file_path:
136 self.input_path_cookie.setText(base64.b64encode(open(file_path, "r").read().encode('utf-8')).decode('utf-8'))
137 self.log_to_console(f"Selected input file: {file_path}")
138
139 def select_input_file(self):
140 file_path, _ = QtWidgets.QFileDialog.getOpenFileName(
141 None, "Select Video File", "",
142 "Video Files (*.mp4 *.avi *.mkv *.mov);;All Files (*)"
143 )
144 if file_path:
145 self.input_path_file.setText(file_path)
146 self.log_to_console(f"Selected input file: {file_path}")
147
148 def select_output_folder(self):
149 folder_path = QtWidgets.QFileDialog.getExistingDirectory(
150 None, "Select Output Folder"
151 )
152 if folder_path:
153 self.output_path_file.setText(folder_path)
154 self.log_to_console(f"Selected output folder: {folder_path}")
155
156 def start_hls_conversion(self):
157 # now = datetime.now().strftime("%Y%m%d%H%M%S")
158 input_file = self.input_path_file.text()
159 output_folder = self.output_path_file.text()
160
161 if not input_file or not output_folder:
162 self.log_to_console("\n⚠️ Error: Please select both input file and output folder")
163 return
164
165 if not os.path.exists(input_file):
166 self.log_to_console("\n⚠️ Error: Input file does not exist")
167 return
168
169 thread = threading.Thread(target=self.run_ffmpeg_hls, args=(input_file, output_folder))
170 thread.start()
171 self.log_to_console("---Started HLS conversion...")
172
173 def get_bitrate(self,file_path):
174 cmd = [
175 "ffprobe",
176 "-v", "error",
177 "-select_streams", "v:0",
178 "-show_entries", "stream=bit_rate",
179 "-of", "default=noprint_wrappers=1:nokey=1",
180 file_path
181 ]
182
183 try:
184 result = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
185 bitrate = result.stdout.decode().strip()
186 if not bitrate or "N/A" in bitrate:
187 return "5000k"
188 return f"{int(bitrate) // 5000}k"
189 except subprocess.CalledProcessError:
190 return "5000k"
191
192 def compress_ts_file(self,file_path,output_folder):
193 file_size = os.path.getsize(file_path)
194 MAX_SIZE = 9000000
195 if file_size > MAX_SIZE:
196 self.log_to_console(f"File {file_path} ({file_size} bytes) vượt 9MB, đang nén lại...")
197
198 bitrate = self.get_bitrate(file_path)
199
200 dir_name = os.path.dirname(file_path)
201 base_name = os.path.basename(file_path)
202 temp_file = f"{output_folder}/temp_{base_name}"
203
204 cmd = [
205 "ffmpeg",
206 "-i", file_path,
207 "-c:v", "libx264",
208 "-b:v", bitrate,
209 "-minrate", bitrate,
210 "-maxrate", bitrate,
211 "-bufsize", "2M",
212 "-preset", "ultrafast",
213 "-c:a", "copy",
214 "-f", "mpegts",
215 temp_file
216 ]
217
218 try:
219 subprocess.run(cmd, check=True, stderr=subprocess.PIPE)
220 new_size = os.path.getsize(temp_file)
221 self.log_to_console(f"⚠️Kích thước sau nén: {new_size} bytes")
222
223 # Kiểm tra xem file nén có nhỏ hơn 10MB không
224 if new_size > MAX_SIZE:
225 self.log_to_console(f"⚠️File {temp_file} vẫn vượt 9MB ({new_size} bytes), thử nén mạnh hơn...")
226 cmd = [
227 "ffmpeg",
228 "-i", file_path,
229 "-c:v", "libx264",
230 "-b:v", bitrate,
231 "-preset", "medium",
232 "-c:a", "copy",
233 "-f", "mpegts",
234 temp_file
235 ]
236 subprocess.run(cmd, check=True, stderr=subprocess.PIPE)
237 new_size = os.path.getsize(temp_file)
238 self.log_to_console(f"⚠️Kích thước sau nén lần 2: {new_size} bytes")
239
240 # Thay thế file gốc nếu nén thành công
241 if new_size <= MAX_SIZE:
242 os.replace(temp_file, file_path)
243 self.log_to_console(f"⚠️Đã nén {file_path} xuống {new_size} bytes.")
244 else:
245 self.log_to_console(f"⚠️Không thể nén {file_path} xuống dưới 9MB với bitrate hiện tại.")
246 os.remove(temp_file)
247 except subprocess.CalledProcessError as e:
248 self.log_to_console(f"⚠️Lỗi khi nén file {file_path}: {e.stderr.decode()}")
249 if os.path.exists(temp_file):
250 os.remove(temp_file)
251 else:
252 self.log_to_console(f"✅File {file_path} ({file_size} bytes) dưới 9MB, không cần nén.")
253
254
255 def run_ffmpeg_hls(self, input_file, output_folder):
256 try:
257 print(self.time.text())
258
259 output_playlist = os.path.join(output_folder, f"{now}.m3u8")
260 # ffmpeg_cmd = [
261 # "ffmpeg",
262 # "-i", input_file,
263 # "-c:v", "libx264",
264 # "-c:a", "aac",
265 # "-f", "hls",
266 # "-hls_time", self.time.text(),
267 # "-hls_list_size", "0",
268 # "-hls_segment_filename", os.path.join(output_folder, now+"00%d.ts"),
269 # output_playlist
270 # ]
271
272 ffmpeg_cmd = [
273 "ffmpeg", '-hwaccel', 'cuda', '-i', input_file,
274 '-c:v', 'h264_nvenc', '-preset', 'p4', '-b:v', '5M',
275 '-c:a', 'aac', '-b:a', '128k', '-ac', '2',
276 '-hls_time', self.time.text(),
277 '-hls_playlist_type', 'vod',
278 '-hls_segment_type', 'mpegts',
279 '-hls_flags', 'independent_segments+split_by_time',
280 "-hls_segment_filename", os.path.join(output_folder, now+"00%d.ts"),
281 '-force_key_frames', f"expr:gte(t,n_forced*"+self.time.text()+")",
282 '-map', '0:v:0', '-map', '0:a:0',
283 '-gpu', '0',
284 output_playlist
285 ]
286
287 process = subprocess.Popen(
288 ffmpeg_cmd,
289 stdout=subprocess.PIPE,
290 stderr=subprocess.PIPE,
291 universal_newlines=True
292 )
293
294 while True:
295 output = process.stderr.readline()
296 if output == '' and process.poll() is not None:
297 break
298 if output:
299 self.log_to_console(output.strip())
300
301 if process.returncode == 0:
302 self.log_to_console("\n✅ HLS conversion completed successfully")
303 self.log_to_console("\n✅ HLS start check ts MB")
304 for file in os.listdir(output_folder):
305 if file.endswith(".ts"):
306 self.compress_ts_file(f"{output_folder}/{file}",output_folder)
307 self.log_to_console("\n✅ HLS start check ts MB completed successfully")
308 else:
309 self.log_to_console("\n⚠️ HLS conversion failed")
310
311 except Exception as e:
312 self.log_to_console(f"\n⚠️ Error during HLS conversion: {str(e)}")
313
314 def start_upload_process(self):
315 input_file = self.input_path_file.text()
316 output_folder = self.output_path_file.text()
317
318 if not input_file or not output_folder:
319 self.log_to_console("\n⚠️ Error: Please select both input file and output folder")
320 return
321
322 self.log_to_console("---Starting upload process...")
323 thread = threading.Thread(target=self.upload_file, args=(output_folder,))
324 thread.start()
325
326 def upload_file(self, output_folder):
327 cookie = self.input_path_cookie.text()
328 api = self.api.currentText()
329 key = self.input_key.text()
330 if api == 'TikTok V1':
331 url_api = f"https://https://upload-v2.cuong.one/?key={key}&cookie={cookie}"
332 elif api == "Google V1":
333 url_api = f"https://upload-lh3.cuong.shop/?key={key}"
334 data_list = open(f'{now}.json', 'w')
335 # api = API.TikTok(cookie=cookie)
336 data_list = [f for f in os.listdir(output_folder) if f.endswith('.ts')]
337 len_str = len(data_list)
338 data = {}
339 s = 0
340 for i in data_list:
341 s += 1
342 if i in data and data[i] == "":
343 continue
344 try:
345 # upload = api.main(f'{output_folder}/{i}')
346 files = {
347 'file': open(f'{output_folder}/{i}', 'rb').read(),
348 "time":int(time.time())
349 }
350 upload = requests.post(url_api, files=files).json()['url']
351 data[i] = upload
352 open('data.txt', 'a+').write(f'{upload}\n')
353 self.log_to_console(f'{s}/{len_str}')
354 # self.log_to_console(upload)
355 except Exception as e:
356 data[i] = ""
357 self.log_to_console(f"\n⚠️Upload failed: {str(e)}")
358 with open(f'{now}.json', 'w', encoding="utf-8") as f:
359 json.dump(data, f, indent=4, ensure_ascii=False)
360 self.log_to_console("\n✅Upload completed successfully")
361 with open(f'{output_folder}/{now}.m3u8', 'r', encoding='utf-8') as file:
362 file_m3u8 = file.read()
363
364 with open(f'{now}.json', 'r', encoding='utf-8') as file:
365 data_list = json.loads(file.read())
366
367 with open(f'{now}.m3u8', 'w', encoding='utf-8') as output_file:
368 data = file_m3u8
369 for key, value in data_list.items():
370 data = data.replace(key, value)
371
372 output_file.write(data)
373 # print(data)
374 self.log_to_console("\nReplace m3u8 successfully")
375
376
377
378
379if __name__ == "__main__":
380 import sys
381 app = QtWidgets.QApplication(sys.argv)
382 Tool = QtWidgets.QMainWindow()
383 ui = Ui_Tool()
384 ui.setupUi(Tool)
385 Tool.show()
386 sys.exit(app.exec())
387 