Advertisement
Najeebsk

IPTV-URLS-PLAYER4.0.pyw

Jul 10th, 2024 (edited)
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.07 KB | None | 0 0
  1. import tkinter as tk
  2. from tkinter import ttk, messagebox, filedialog
  3. import vlc
  4. import subprocess
  5. import threading
  6. import time
  7.  
  8. # Path to VLC executable
  9. VLC_PATH = r"C:\Program Files\VideoLAN\VLC\vlc.exe"
  10.  
  11. class ChannelPlayer:
  12.     def __init__(self, root):
  13.         self.root = root
  14.         self.root.title("Najeeb Live Videos and IPTV Channels Player")
  15.        
  16.         self.channels = {}
  17.         self.current_instance = None
  18.         self.player = None
  19.         self.media = None
  20.         self.is_dragging_slider = False
  21.         self.is_fullscreen = False
  22.         self.is_muted = False
  23.         self.process = None
  24.  
  25.         self.create_widgets()  # Initialize GUI widgets
  26.    
  27.     def load_channels(self, file_path):
  28.         self.channels.clear()
  29.         try:
  30.             with open(file_path, 'r', encoding='utf-8') as file:
  31.                 for line in file:
  32.                     parts = line.strip().split(maxsplit=1)
  33.                     if len(parts) == 2:
  34.                         self.channels[parts[0]] = parts[1]
  35.             self.update_channel_dropdown()
  36.         except FileNotFoundError:
  37.             messagebox.showerror("Error", f"File not found: {file_path}")
  38.         except UnicodeDecodeError:
  39.             messagebox.showerror("Error", "Error decoding the file. Please ensure it is in UTF-8 format.")
  40.         except Exception as e:
  41.             messagebox.showerror("Error", str(e))
  42.    
  43.     def update_channel_dropdown(self):
  44.         self.channel_dropdown['values'] = list(self.channels.keys())
  45.    
  46.     def create_widgets(self):
  47.         style = ttk.Style()
  48.         style.configure('TButton', font=('Helvetica', 10))
  49.         style.configure('TCombobox', font=('Helvetica', 10))
  50.        
  51.         # Search field for channel title
  52.         self.search_label = ttk.Label(self.root, text="Search Channel Title:")
  53.         self.search_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
  54.  
  55.         self.search_var = tk.StringVar()
  56.         self.search_entry = ttk.Entry(self.root, textvariable=self.search_var)
  57.         self.search_entry.grid(row=0, column=1, columnspan=2, padx=5, pady=5, sticky="ew")
  58.         self.search_entry.bind("<KeyRelease>", self.filter_channels)
  59.  
  60.         # Browse button for URLs file
  61.         self.browse_button = ttk.Button(self.root, text="Browse", command=self.browse_file)
  62.         self.browse_button.grid(row=0, column=3, padx=5, pady=5, sticky="ew")
  63.  
  64.         # Channel selection
  65.         self.channel_var = tk.StringVar()
  66.         self.channel_dropdown = ttk.Combobox(self.root, textvariable=self.channel_var)
  67.         self.channel_dropdown.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="ew")
  68.        
  69.         # Preview button
  70.         self.preview_button = ttk.Button(self.root, text="Preview", command=self.preview_channel)
  71.         self.preview_button.grid(row=1, column=2, padx=5, pady=5, sticky="ew")
  72.  
  73.         # Stop preview button
  74.         self.stop_preview_button = ttk.Button(self.root, text="Stop Preview", command=self.stop_preview)
  75.         self.stop_preview_button.grid(row=1, column=3, padx=5, pady=5, sticky="ew")
  76.  
  77.         # Play button
  78.         self.play_button = ttk.Button(self.root, text="Play", command=self.play_channel)
  79.         self.play_button.grid(row=1, column=4, padx=5, pady=5, sticky="ew")
  80.  
  81.         # Volume control
  82.         self.volume_slider = ttk.Scale(self.root, from_=0, to=100, orient=tk.HORIZONTAL, command=self.set_volume)
  83.         self.volume_slider.set(50)  # Set initial volume to 50%
  84.         self.volume_slider.grid(row=1, column=5, padx=5, pady=5, sticky="ew")
  85.  
  86.         # Mute button
  87.         self.mute_button = ttk.Button(self.root, text="Mute", command=self.toggle_mute)
  88.         self.mute_button.grid(row=1, column=6, padx=5, pady=5, sticky="ew")
  89.  
  90.         # Full screen button
  91.         self.fullscreen_button = ttk.Button(self.root, text="Full Screen", command=self.toggle_fullscreen)
  92.         self.fullscreen_button.grid(row=1, column=7, padx=5, pady=5, sticky="ew")
  93.  
  94.         # Capture video button
  95.         self.capture_video_button = ttk.Button(self.root, text="Capture Video", command=self.capture_video)
  96.         self.capture_video_button.grid(row=4, column=0, padx=5, pady=5, sticky="ew")
  97.  
  98.         # Record audio button
  99.         self.record_audio_button = ttk.Button(self.root, text="Record Audio", command=self.record_audio)
  100.         self.record_audio_button.grid(row=4, column=1, padx=5, pady=5, sticky="ew")
  101.  
  102.         # Stop recording button
  103.         self.stop_recording_button = ttk.Button(self.root, text="Stop Recording", command=self.stop_recording)
  104.         self.stop_recording_button.grid(row=4, column=2, padx=5, pady=5, sticky="ew")
  105.  
  106.         # Capture screenshots button
  107.         self.capture_screenshots_button = ttk.Button(self.root, text="Capture Screenshots", command=self.capture_screenshots)
  108.         self.capture_screenshots_button.grid(row=4, column=3, padx=5, pady=5, sticky="ew")
  109.  
  110.         # Copy URL button
  111.         self.copy_url_button = ttk.Button(self.root, text="Copy URL", command=self.copy_url_to_clipboard)
  112.         self.copy_url_button.grid(row=4, column=4, padx=5, pady=5, sticky="ew")
  113.  
  114.         # VLC video frame
  115.         self.video_frame = tk.Frame(self.root, bg="black", height=300)
  116.         self.video_frame.grid(row=2, column=0, columnspan=8, padx=5, pady=5, sticky="nsew")
  117.  
  118.         # Video control slider
  119.         self.video_slider = ttk.Scale(self.root, from_=0, to=1000, orient=tk.HORIZONTAL)
  120.         self.video_slider.grid(row=3, column=0, columnspan=8, padx=5, pady=5, sticky="ew")
  121.         self.video_slider.bind("<ButtonPress-1>", self.slider_pressed)
  122.         self.video_slider.bind("<ButtonRelease-1>", self.slider_released)
  123.  
  124.         self.root.grid_rowconfigure(2, weight=1)
  125.         self.root.grid_rowconfigure(3, weight=0)
  126.         self.root.grid_columnconfigure(0, weight=1)
  127.         self.root.grid_columnconfigure(1, weight=1)
  128.         self.root.grid_columnconfigure(2, weight=1)
  129.         self.root.grid_columnconfigure(3, weight=1)
  130.         self.root.grid_columnconfigure(4, weight=1)
  131.         self.root.grid_columnconfigure(5, weight=1)
  132.         self.root.grid_columnconfigure(6, weight=1)
  133.         self.root.grid_columnconfigure(7, weight=1)
  134.         self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
  135.  
  136.     def browse_file(self):
  137.         file_path = filedialog.askopenfilename(
  138.             title="Select URLs file",
  139.             filetypes=(("Text files", "*.txt"), ("All files", "*.*"))
  140.         )
  141.         if file_path:
  142.             self.load_channels(file_path)
  143.  
  144.     def filter_channels(self, event):
  145.         search_term = self.search_var.get().lower()
  146.         filtered_channels = [channel for channel in self.channels.keys() if search_term in channel.lower()]
  147.         self.channel_dropdown['values'] = filtered_channels
  148.  
  149.     def preview_channel(self):
  150.         self.stop_preview()
  151.         channel = self.channel_var.get()
  152.         if channel and channel in self.channels:
  153.             url = self.channels[channel]
  154.             try:
  155.                 self.current_instance = vlc.Instance()
  156.                 self.player = self.current_instance.media_player_new()
  157.                 self.player.set_hwnd(self.video_frame.winfo_id())
  158.                 self.media = self.current_instance.media_new(url)
  159.                 self.player.set_media(self.media)
  160.                 self.player.play()
  161.                 self.update_video_slider()
  162.             except Exception as e:
  163.                 messagebox.showerror("Error", str(e))
  164.  
  165.     def stop_preview(self):
  166.         if self.player:
  167.             self.player.stop()
  168.             self.player.release()
  169.             self.player = None
  170.         if self.current_instance:
  171.             self.current_instance.release()
  172.             self.current_instance = None
  173.  
  174.     def play_channel(self):
  175.         self.stop_preview()
  176.         channel = self.channel_var.get()
  177.         if channel and channel in self.channels:
  178.             url = self.channels[channel]
  179.             try:
  180.                 subprocess.Popen([VLC_PATH, url])
  181.             except Exception as e:
  182.                 messagebox.showerror("Error", str(e))
  183.  
  184.     def set_volume(self, value):
  185.         if self.player:
  186.             self.player.audio_set_volume(int(float(value)))
  187.  
  188.     def toggle_mute(self):
  189.         if self.player:
  190.             self.is_muted = not self.is_muted
  191.             self.player.audio_toggle_mute()
  192.             self.mute_button.config(text="Unmute" if self.is_muted else "Mute")
  193.  
  194.     def slider_pressed(self, event):
  195.         self.is_dragging_slider = True
  196.  
  197.     def slider_released(self, event):
  198.         self.is_dragging_slider = False
  199.         self.set_position(self.video_slider.get())
  200.  
  201.     def set_position(self, value):
  202.         if self.player:
  203.             self.player.set_position(float(value) / 1000.0)
  204.  
  205.     def update_video_slider(self):
  206.         if self.player and self.player.is_playing() and not self.is_dragging_slider:
  207.             length = self.player.get_length()
  208.             if length > 0:
  209.                 current_time = self.player.get_time()
  210.                 position = int(current_time / length * 1000)
  211.                 self.video_slider.set(position)
  212.         self.root.after(1000, self.update_video_slider)
  213.  
  214.     def toggle_fullscreen(self):
  215.         self.is_fullscreen = not self.is_fullscreen
  216.         self.root.attributes("-fullscreen", self.is_fullscreen)
  217.         if not self.is_fullscreen:
  218.             self.root.geometry("800x600")
  219.  
  220.     def on_closing(self):
  221.         self.stop_preview()
  222.         self.root.destroy()
  223.  
  224.     def capture_video(self):
  225.         channel = self.channel_var.get()
  226.         if channel and channel in self.channels:
  227.             url = self.channels[channel]
  228.             filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
  229.             if filename:
  230.                 command = ['ffmpeg', '-y', '-i', url, '-t', '03:55:00', '-c', 'copy', filename]
  231.                 threading.Thread(target=lambda: subprocess.run(command)).start()
  232.                 messagebox.showinfo("Capturing", f"Capturing 03:55 minutes of video to {filename}")
  233.         else:
  234.             messagebox.showerror("Error", "Selected channel is not valid.")
  235.  
  236.     def record_audio(self):
  237.         channel = self.channel_var.get()
  238.         if channel and channel in self.channels:
  239.             url = self.channels[channel]
  240.             filename = filedialog.asksaveasfilename(defaultextension=".mp3", filetypes=[("MP3 files", "*.mp3")])
  241.             if filename:
  242.                 command = ['ffmpeg', '-y', '-i', url, '-f', 'mp3', '-c:a', 'libmp3lame', filename]
  243.                 self.process = subprocess.Popen(command)
  244.                 messagebox.showinfo("Recording", f"Recording audio to {filename}")
  245.         else:
  246.             messagebox.showerror("Error", "Selected channel is not valid.")
  247.  
  248.     def stop_recording(self):
  249.         if self.process:
  250.             self.process.terminate()
  251.             self.process = None
  252.             messagebox.showinfo("Stopped", "Recording stopped")
  253.  
  254.     def capture_screenshots(self):
  255.         if self.player and self.player.get_media():
  256.             filename_base = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
  257.             if filename_base:
  258.                 interval = 5
  259.                 num_screenshots = 5
  260.                 for i in range(num_screenshots):
  261.                     time.sleep(interval)
  262.                     filename = f"{filename_base}_{i + 1}.png"
  263.                     self.player.video_take_snapshot(0, filename, 0, 0)
  264.                 messagebox.showinfo("Capturing Screenshots", f"Captured {num_screenshots} screenshots every {interval} seconds to {filename_base}")
  265.  
  266.     def copy_url_to_clipboard(self):
  267.         channel = self.channel_var.get()
  268.         if channel and channel in self.channels:
  269.             url = self.channels[channel]
  270.             self.root.clipboard_clear()
  271.             self.root.clipboard_append(url)
  272.             messagebox.showinfo("Copied", "URL copied to clipboard")
  273.         else:
  274.             messagebox.showerror("Error", "No channel selected or channel not valid")
  275.  
  276. if __name__ == "__main__":
  277.     root = tk.Tk()
  278.     app = ChannelPlayer(root)
  279.     root.mainloop()
  280.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement