Najeebsk

IPTV-PLAYER-ALL.pyw

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