Advertisement
Najeebsk

IPTV-PLAYER-ALL4.0.pyw

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