Advertisement
Najeebsk

FFMPEG-TOOLS-2.0.pyw

Jul 2nd, 2024
725
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.94 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import filedialog, messagebox
  3. import subprocess
  4. import os
  5. import yt_dlp
  6. import sys
  7. import threading
  8. from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QVBoxLayout, QWidget
  9. from PyQt5.QtCore import QThread, pyqtSignal, pyqtSlot
  10.  
  11. class VideoToolApp:
  12.     def __init__(self, root):
  13.         self.root = root
  14.         self.root.title("Najeeb Advanced Video Tool with FFmpeg")
  15.         self.root.geometry("620x460")
  16.         self.root.configure(bg='#4a4a4a')
  17.  
  18.         # Video File Path
  19.         self.video_path = tk.StringVar()
  20.         tk.Label(root, text="Video File Path:", bg='#1d1f21', fg='white').grid(row=0, column=0, padx=10, pady=10, sticky='e')
  21.         tk.Entry(root, textvariable=self.video_path, width=50, bg='#282a2e', fg='white').grid(row=0, column=1, padx=10, pady=10)
  22.         tk.Button(root, text="Browse", command=self.browse_file, bg='#373b41', fg='white').grid(row=0, column=2, padx=10, pady=10)
  23.  
  24.         # YouTube and Other URLs
  25.         self.url = tk.StringVar()
  26.         tk.Label(root, text="Video URL:", bg='#1d1f21', fg='white').grid(row=1, column=0, padx=10, pady=10, sticky='e')
  27.         tk.Entry(root, textvariable=self.url, width=50, bg='#282a2e', fg='white').grid(row=1, column=1, padx=10, pady=10)
  28.         tk.Button(root, text="Download", command=self.download_video, bg='#373b41', fg='white').grid(row=1, column=2, padx=10, pady=10)
  29.  
  30.         # IPTV URL
  31.         self.iptv_url = tk.StringVar()
  32.         tk.Label(root, text="IPTV URL:", bg='#1d1f21', fg='white').grid(row=2, column=0, padx=10, pady=10, sticky='e')
  33.         tk.Entry(root, textvariable=self.iptv_url, width=50, bg='#282a2e', fg='white').grid(row=2, column=1, padx=10, pady=10)
  34.         tk.Button(root, text="Capture", command=self.capture_iptv, bg='#373b41', fg='white').grid(row=2, column=2, padx=10, pady=10)
  35.  
  36.         # Start and End Time
  37.         self.start_time = tk.StringVar(value="00:00:00")
  38.         self.end_time = tk.StringVar(value="00:00:00")
  39.         tk.Label(root, text="Start Time (HH:MM:SS):", bg='#1d1f21', fg='white').grid(row=3, column=0, padx=10, pady=10, sticky='e')
  40.         tk.Entry(root, textvariable=self.start_time, width=20, bg='#282a2e', fg='white').grid(row=3, column=1, padx=10, pady=10, sticky='w')
  41.         tk.Label(root, text="End Time (HH:MM:SS):", bg='#1d1f21', fg='white').grid(row=4, column=0, padx=10, pady=10, sticky='e')
  42.         tk.Entry(root, textvariable=self.end_time, width=20, bg='#282a2e', fg='white').grid(row=4, column=1, padx=10, pady=10, sticky='w')
  43.  
  44.         # Output File Path
  45.         self.output_path = tk.StringVar()
  46.         tk.Label(root, text="Output File Path:", bg='#1d1f21', fg='white').grid(row=5, column=0, padx=10, pady=10, sticky='e')
  47.         tk.Entry(root, textvariable=self.output_path, width=50, bg='#282a2e', fg='white').grid(row=5, column=1, padx=10, pady=10)
  48.         tk.Button(root, text="Save As", command=self.save_as_file, bg='#373b41', fg='white').grid(row=5, column=2, padx=10, pady=10)
  49.  
  50.         # Frame Interval for Image Extraction
  51.         self.frame_interval = tk.StringVar()
  52.         tk.Label(root, text="Frame Interval (seconds):", bg='#1d1f21', fg='white').grid(row=6, column=0, padx=10, pady=10, sticky='e')
  53.         tk.Entry(root, textvariable=self.frame_interval, width=20, bg='#282a2e', fg='white').grid(row=6, column=1, padx=10, pady=10, sticky='w')
  54.  
  55.         # Buttons for operations
  56.         tk.Button(root, text="Cut Video", command=self.cut_video, bg='#cc0066', fg='white').grid(row=7, column=0, padx=10, pady=20)
  57.         tk.Button(root, text="Merge Videos", command=self.merge_videos, bg='#4c9900', fg='white').grid(row=7, column=1, padx=10, pady=20)
  58.         tk.Button(root, text="Convert Video", command=self.convert_video, bg='#cc6600', fg='white').grid(row=7, column=2, padx=10, pady=20)
  59.         tk.Button(root, text="Extract Pictures", command=self.extract_pictures, bg='#660000', fg='white').grid(row=6, column=2, padx=10, pady=20)
  60.  
  61.         # Desktop Recorder Button
  62.         tk.Button(root, text="Desktop Recorder", command=self.desktop_recorder, bg='#0066cc', fg='white').grid(row=4, column=2, padx=10, pady=20)
  63.  
  64.     def browse_file(self):
  65.         file_path = filedialog.askopenfilename(filetypes=[("Video files", "*.*")])
  66.         if file_path:
  67.             self.video_path.set(file_path)
  68.  
  69.     def save_as_file(self):
  70.         file_path = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("All files", "*.*")])
  71.         if file_path:
  72.             self.output_path.set(file_path)
  73.  
  74.     def download_video(self):
  75.         url = self.url.get()
  76.         start_time = self.start_time.get()
  77.         end_time = self.end_time.get()
  78.         if not url:
  79.             messagebox.showerror("Error", "Video URL must be provided")
  80.             return
  81.         try:
  82.             ydl_opts = {}
  83.             with yt_dlp.YoutubeDL(ydl_opts) as ydl:
  84.                 info = ydl.extract_info(url, download=False)
  85.                 download_path = filedialog.asksaveasfilename(defaultextension=".mp4", initialfile=info.get('title', 'video'), filetypes=[("All files", "*.*")])
  86.                 if download_path:
  87.                     ydl_opts = {'outtmpl': download_path}
  88.                     with yt_dlp.YoutubeDL(ydl_opts) as ydl:
  89.                         ydl.download([url])
  90.                     messagebox.showinfo("Success", "Video downloaded successfully")
  91.                     self.video_path.set(download_path)
  92.                     if start_time != "00:00:00" or end_time != "00:00:00":
  93.                         self.cut_video()
  94.                         self.extract_pictures()
  95.         except Exception as e:
  96.             messagebox.showerror("Error", f"Failed to download video: {str(e)}")
  97.  
  98.     def capture_iptv(self):
  99.         iptv_url = self.iptv_url.get()
  100.         output_file = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("All files", "*.*")])
  101.  
  102.         if not iptv_url or not output_file:
  103.             messagebox.showerror("Error", "IPTV URL and output file path must be provided")
  104.             return
  105.  
  106.         try:
  107.             subprocess.run(["ffmpeg", "-i", iptv_url, "-c", "copy", output_file], check=True)
  108.             messagebox.showinfo("Success", "IPTV stream captured successfully")
  109.             self.video_path.set(output_file)
  110.         except subprocess.CalledProcessError as e:
  111.             messagebox.showerror("Error", f"Failed to capture IPTV stream: {str(e)}")
  112.  
  113.     def cut_video(self):
  114.         input_file = self.video_path.get()
  115.         start_time = self.start_time.get()
  116.         end_time = self.end_time.get()
  117.         output_file = self.output_path.get()
  118.  
  119.         if not input_file or not start_time or not end_time or not output_file:
  120.             messagebox.showerror("Error", "All fields must be filled")
  121.             return
  122.  
  123.         try:
  124.             subprocess.run(["ffmpeg", "-i", input_file, "-ss", start_time, "-to", end_time, "-c", "copy", output_file], check=True)
  125.             messagebox.showinfo("Success", "Video cut successfully")
  126.         except subprocess.CalledProcessError as e:
  127.             messagebox.showerror("Error", f"Failed to cut video: {str(e)}")
  128.  
  129.     def merge_videos(self):
  130.         files = filedialog.askopenfilenames(filetypes=[("Video files", "*.*")])
  131.         if not files:
  132.             return
  133.  
  134.         output_file = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("All files", "*.*")])
  135.         if not output_file:
  136.             return
  137.  
  138.         with open('file_list.txt', 'w') as file_list:
  139.             for file in files:
  140.                 file_list.write(f"file '{file}'\n")
  141.  
  142.         try:
  143.             subprocess.run(["ffmpeg", "-f", "concat", "-safe", "0", "-i", "file_list.txt", "-c", "copy", output_file], check=True)
  144.             os.remove('file_list.txt')
  145.             messagebox.showinfo("Success", "Videos merged successfully")
  146.         except subprocess.CalledProcessError as e:
  147.             os.remove('file_list.txt')
  148.             messagebox.showerror("Error", f"Failed to merge videos: {str(e)}")
  149.  
  150.     def convert_video(self):
  151.         input_file = self.video_path.get()
  152.         output_file = self.output_path.get()
  153.  
  154.         if not input_file or not output_file:
  155.             messagebox.showerror("Error", "Input and Output paths must be filled")
  156.             return
  157.  
  158.         try:
  159.             subprocess.run(["ffmpeg", "-i", input_file, output_file], check=True)
  160.             messagebox.showinfo("Success", "Video converted successfully")
  161.         except subprocess.CalledProcessError as e:
  162.             messagebox.showerror("Error", f"Failed to convert video: {str(e)}")
  163.  
  164.     def extract_pictures(self):
  165.         input_file = self.video_path.get()
  166.         output_dir = filedialog.askdirectory()
  167.         frame_interval = self.frame_interval.get()
  168.  
  169.         if not input_file or not output_dir or not frame_interval:
  170.             messagebox.showerror("Error", "Video file, output directory, and frame interval must be provided")
  171.             return
  172.  
  173.         try:
  174.             subprocess.run(["ffmpeg", "-i", input_file, "-vf", f"fps=1/{frame_interval}", f"{output_dir}/frame%04d.png"], check=True)
  175.             messagebox.showinfo("Success", "Pictures extracted successfully")
  176.         except subprocess.CalledProcessError as e:
  177.             messagebox.showerror("Error", f"Failed to extract pictures: {str(e)}")
  178.  
  179.     def desktop_recorder(self):
  180.         def start_pyqt_recorder():
  181.             ffmpeg_path = r'C:\CMDER\APP\ffmpeg.exe'  # Update with your ffmpeg path
  182.             app = QApplication(sys.argv)
  183.             ex = PyQtApp(ffmpeg_path)
  184.             ex.show()
  185.             sys.exit(app.exec_())
  186.  
  187.         recorder_thread = threading.Thread(target=start_pyqt_recorder)
  188.         recorder_thread.start()
  189.  
  190. class Recorder(QThread):
  191.     changeStatus = pyqtSignal(str)
  192.  
  193.     def __init__(self, ffmpeg_path):
  194.         super().__init__()
  195.         self.recording = False
  196.         self.process = None
  197.         self.ffmpeg_path = ffmpeg_path
  198.  
  199.     def run(self):
  200.         self.recording = True
  201.         command = [
  202.             self.ffmpeg_path,
  203.             '-y',  # Overwrite output file if it exists
  204.             '-f', 'gdigrab',
  205.             '-framerate', '20',
  206.             '-i', 'desktop',  # Capture the entire desktop
  207.             '-c:v', 'libx264',
  208.             '-preset', 'ultrafast',
  209.             'output.mp4'
  210.         ]
  211.  
  212.         try:
  213.             self.process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
  214.             self.changeStatus.emit("Recording started...")
  215.  
  216.             while self.recording:
  217.                 output = self.process.stderr.readline()
  218.                 if output == '' and self.process.poll() is not None:
  219.                     break
  220.                 if output:
  221.                     print(output.strip())
  222.  
  223.             if self.process.poll() is None:
  224.                 self.process.terminate()
  225.                 self.process.wait()
  226.             self.changeStatus.emit("Recording stopped and saved to output.mp4.")
  227.         except Exception as e:
  228.             self.changeStatus.emit(f"Error: {e}")
  229.             self.recording = False
  230.  
  231.     def stop_recording(self):
  232.         self.recording = False
  233.         if self.process and self.process.poll() is None:
  234.             self.process.terminate()
  235.             self.process.wait()
  236.  
  237. class PyQtApp(QMainWindow):
  238.     def __init__(self, ffmpeg_path):
  239.         super().__init__()
  240.         self.setWindowTitle("Desktop Video Recorder")
  241.         self.setGeometry(100, 100, 400, 200)
  242.  
  243.         self.recorder = None
  244.         self.ffmpeg_path = ffmpeg_path
  245.  
  246.         self.initUI()
  247.  
  248.     def initUI(self):
  249.         self.status_label = QLabel("Press Start to begin recording the desktop.", self)
  250.         self.status_label.resize(400, 50)
  251.  
  252.         self.start_button = QPushButton("Start Recording", self)
  253.         self.start_button.clicked.connect(self.start_recording)
  254.  
  255.         self.stop_button = QPushButton("Stop Recording", self)
  256.         self.stop_button.clicked.connect(self.stop_recording)
  257.         self.stop_button.setEnabled(False)
  258.  
  259.         layout = QVBoxLayout()
  260.         layout.addWidget(self.status_label)
  261.         layout.addWidget(self.start_button)
  262.         layout.addWidget(self.stop_button)
  263.  
  264.         container = QWidget()
  265.         container.setLayout(layout)
  266.         self.setCentralWidget(container)
  267.  
  268.     def start_recording(self):
  269.         self.recorder = Recorder(self.ffmpeg_path)
  270.         self.recorder.changeStatus.connect(self.updateStatus)
  271.         self.recorder.start()
  272.         self.start_button.setEnabled(False)
  273.         self.stop_button.setEnabled(True)
  274.  
  275.     def stop_recording(self):
  276.         if self.recorder:
  277.             self.recorder.stop_recording()
  278.             self.recorder.wait()
  279.             self.stop_button.setEnabled(False)
  280.             self.start_button.setEnabled(True)
  281.  
  282.     @pyqtSlot(str)
  283.     def updateStatus(self, message):
  284.         self.status_label.setText(message)
  285.         print(message)  # Print to console for debugging
  286.  
  287. if __name__ == "__main__":
  288.     root = tk.Tk()
  289.     app = VideoToolApp(root)
  290.     root.mainloop()
  291.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement