Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import tkinter as tk
- from tkinter import ttk, messagebox, filedialog
- import vlc
- import subprocess
- import threading
- import time
- # Path to VLC executable
- VLC_PATH = r"C:\Program Files\VideoLAN\VLC\vlc.exe"
- class ChannelPlayer:
- def __init__(self, root):
- self.root = root
- self.root.title("Najeeb Live Videos and IPTV Channels Player")
- self.channels = {}
- self.current_instance = None
- self.player = None
- self.media = None
- self.is_dragging_slider = False
- self.is_fullscreen = False
- self.is_muted = False
- self.process = None
- self.recording_process = None # To store the subprocess for recording
- self.create_widgets()
- self.auto_load_channels()
- def auto_load_channels(self):
- script_dir = os.path.dirname(os.path.abspath(__file__))
- channels_dir = os.path.join(script_dir, "CHANNELS")
- if not os.path.exists(channels_dir):
- os.makedirs(channels_dir)
- playlist_files = [file for file in os.listdir(channels_dir) if file.endswith(('.m3u', '.m3u8', '.txt'))]
- for file_name in playlist_files:
- file_path = os.path.join(channels_dir, file_name)
- self.load_channels(file_path)
- def load_channels(self, file_path):
- try:
- with open(file_path, 'r', encoding='utf-8') as file:
- for line in file:
- parts = line.strip().split(maxsplit=1)
- if len(parts) == 2:
- self.channels[parts[0]] = parts[1]
- self.update_channel_dropdown()
- except FileNotFoundError:
- messagebox.showerror("Error", f"File not found: {file_path}")
- except UnicodeDecodeError:
- messagebox.showerror("Error", "Error decoding the file. Please ensure it is in UTF-8 format.")
- except Exception as e:
- messagebox.showerror("Error", str(e))
- def update_channel_dropdown(self):
- self.channel_dropdown['values'] = list(self.channels.keys())
- def create_widgets(self):
- style = ttk.Style()
- style.configure('TButton', font=('Helvetica', 10))
- style.configure('TCombobox', font=('Helvetica', 10))
- # Search field for channel title
- self.search_label = ttk.Label(self.root, text="Search Channel Title:")
- self.search_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
- self.search_var = tk.StringVar()
- self.search_entry = ttk.Entry(self.root, textvariable=self.search_var)
- self.search_entry.grid(row=0, column=1, columnspan=2, padx=5, pady=5, sticky="ew")
- self.search_entry.bind("<KeyRelease>", self.filter_channels)
- # Browse button for URLs file
- self.browse_button = ttk.Button(self.root, text="Browse", command=self.browse_file)
- self.browse_button.grid(row=0, column=3, padx=5, pady=5, sticky="ew")
- # Channel selection
- self.channel_var = tk.StringVar()
- self.channel_dropdown = ttk.Combobox(self.root, textvariable=self.channel_var)
- self.channel_dropdown.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="ew")
- # Preview button
- self.preview_button = ttk.Button(self.root, text="Preview", command=self.preview_channel)
- self.preview_button.grid(row=1, column=2, padx=5, pady=5, sticky="ew")
- # Stop preview button
- self.stop_preview_button = ttk.Button(self.root, text="Stop Preview", command=self.stop_preview)
- self.stop_preview_button.grid(row=1, column=3, padx=5, pady=5, sticky="ew")
- # Play button
- self.play_button = ttk.Button(self.root, text="Play", command=self.play_channel)
- self.play_button.grid(row=1, column=4, padx=5, pady=5, sticky="ew")
- # Volume control
- self.volume_slider = ttk.Scale(self.root, from_=0, to=200, orient=tk.HORIZONTAL, command=self.set_volume)
- self.volume_slider.set(50) # Set initial volume to 50%
- self.volume_slider.grid(row=1, column=5, padx=5, pady=5, sticky="ew")
- # Mute button
- self.mute_button = ttk.Button(self.root, text="Mute", command=self.toggle_mute)
- self.mute_button.grid(row=1, column=6, padx=5, pady=5, sticky="ew")
- # Full screen button
- self.fullscreen_button = ttk.Button(self.root, text="Full Screen", command=self.toggle_fullscreen)
- self.fullscreen_button.grid(row=1, column=7, padx=5, pady=5, sticky="ew")
- # VLC video frame
- self.video_frame = tk.Frame(self.root, bg="black", height=300)
- self.video_frame.grid(row=2, column=0, columnspan=8, padx=5, pady=5, sticky="nsew")
- # Video control slider
- self.video_slider = ttk.Scale(self.root, from_=0, to=1000, orient=tk.HORIZONTAL)
- self.video_slider.grid(row=3, column=0, columnspan=8, padx=5, pady=5, sticky="ew")
- self.video_slider.bind("<ButtonPress-1>", self.slider_pressed)
- self.video_slider.bind("<ButtonRelease-1>", self.slider_released)
- # Capture video button
- self.capture_video_button = ttk.Button(self.root, text="Capture Video", command=self.capture_video)
- self.capture_video_button.grid(row=4, column=0, padx=5, pady=5, sticky="ew")
- # Record audio button
- self.record_audio_button = ttk.Button(self.root, text="Record Audio", command=self.record_audio)
- self.record_audio_button.grid(row=4, column=1, padx=5, pady=5, sticky="ew")
- # Stop recording button
- self.stop_record_button = ttk.Button(self.root, text="Stop Recording", command=self.stop_recording)
- self.stop_record_button.grid(row=4, column=2, padx=5, pady=5, sticky="ew")
- # Capture screenshots button
- self.capture_screenshots_button = ttk.Button(self.root, text="Capture Screenshots", command=self.capture_screenshots)
- self.capture_screenshots_button.grid(row=4, column=3, padx=5, pady=5, sticky="ew")
- # Copy to clipboard button
- self.copy_button = ttk.Button(self.root, text="Copy URL", command=self.copy_to_clipboard)
- self.copy_button.grid(row=4, column=4, padx=5, pady=5, sticky="ew")
- self.root.grid_rowconfigure(2, weight=1)
- self.root.grid_rowconfigure(3, weight=0)
- self.root.grid_rowconfigure(4, weight=0)
- self.root.grid_columnconfigure(0, weight=1)
- self.root.grid_columnconfigure(1, weight=1)
- self.root.grid_columnconfigure(2, weight=1)
- self.root.grid_columnconfigure(3, weight=1)
- self.root.grid_columnconfigure(4, weight=1)
- self.root.grid_columnconfigure(5, weight=1)
- self.root.grid_columnconfigure(6, weight=1)
- self.root.grid_columnconfigure(7, weight=1)
- self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
- def browse_file(self):
- file_path = filedialog.askopenfilename(
- title="Select URLs file",
- filetypes=(("M3U files", "*.m3u"), ("M3U8 files", "*.m3u8"), ("TEXT files", "*.txt"), ("All files", "*.*"))
- )
- if file_path:
- self.load_channels(file_path)
- def filter_channels(self, event):
- search_term = self.search_var.get().lower()
- filtered_channels = [channel for channel in self.channels.keys() if search_term in channel.lower()]
- self.channel_dropdown['values'] = filtered_channels
- def preview_channel(self):
- self.stop_preview()
- channel = self.channel_var.get()
- if channel and channel in self.channels:
- url = self.channels[channel]
- self.current_instance = vlc.Instance()
- self.player = self.current_instance.media_player_new()
- self.player.set_hwnd(self.video_frame.winfo_id())
- self.media = self.current_instance.media_new(url)
- self.player.set_media(self.media)
- self.player.play()
- self.update_video_slider()
- def stop_preview(self):
- if self.player:
- self.player.stop()
- self.player.release()
- self.player = None
- if self.current_instance:
- self.current_instance.release()
- self.current_instance = None
- def play_channel(self):
- self.stop_preview()
- channel = self.channel_var.get()
- if channel and channel in self.channels:
- url = self.channels[channel]
- subprocess.Popen([VLC_PATH, url])
- def set_volume(self, value):
- if self.player:
- volume = int(float(value))
- if volume > 200:
- volume = 200
- self.player.audio_set_volume(volume)
- def toggle_mute(self):
- if self.player:
- self.is_muted = not self.is_muted
- self.player.audio_toggle_mute()
- self.mute_button.config(text="Unmute" if self.is_muted else "Mute")
- def slider_pressed(self, event):
- self.is_dragging_slider = True
- def slider_released(self, event):
- self.is_dragging_slider = False
- self.set_position(self.video_slider.get())
- def set_position(self, value):
- if self.player:
- self.player.set_position(float(value) / 1000.0)
- def update_video_slider(self):
- if self.player and not self.is_dragging_slider:
- position = self.player.get_position() * 1000
- self.video_slider.set(position)
- self.root.after(1000, self.update_video_slider)
- def toggle_fullscreen(self):
- self.is_fullscreen = not self.is_fullscreen
- self.root.attributes("-fullscreen", self.is_fullscreen)
- self.fullscreen_button.config(text="Exit Full Screen" if self.is_fullscreen else "Full Screen")
- def on_closing(self):
- self.stop_preview()
- if self.process:
- self.process.terminate()
- if self.recording_process:
- self.recording_process.terminate()
- self.root.destroy()
- def capture_video(self):
- try:
- selected_channel = self.channel_var.get().strip()
- if selected_channel in self.channels:
- url = self.channels[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp4", filetypes=[("MP4 files", "*.mp4")])
- if filename:
- command = ['ffmpeg', '-y', '-i', url, '-t', '03:55:00', '-c', 'copy', filename]
- threading.Thread(target=lambda: subprocess.run(command)).start()
- messagebox.showinfo("Capturing", f"Capturing 03:55 minutes of video to {filename}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- except tk.TclError:
- messagebox.showerror("Error", "No text selected.")
- def record_audio(self):
- try:
- selected_channel = self.channel_var.get().strip()
- if selected_channel in self.channels:
- url = self.channels[selected_channel]
- filename = filedialog.asksaveasfilename(defaultextension=".mp3", filetypes=[("MP3 files", "*.mp3")])
- if filename:
- command = ['ffmpeg', '-y', '-i', url, '-f', 'mp3', '-c:a', 'libmp3lame', filename]
- self.process = subprocess.Popen(command)
- messagebox.showinfo("Recording", f"Recording audio to {filename}")
- else:
- messagebox.showerror("Error", "Selected text is not a valid URL.")
- except tk.TclError:
- messagebox.showerror("Error", "No text selected.")
- def stop_recording(self):
- if self.process:
- self.process.terminate()
- self.process = None
- messagebox.showinfo("Stopped", "Recording stopped")
- def capture_screenshots(self):
- if self.player.get_media():
- filename_base = filedialog.asksaveasfilename(defaultextension=".png", filetypes=[("PNG files", "*.png")])
- if filename_base:
- interval = 5
- num_screenshots = 5
- for i in range(num_screenshots):
- time.sleep(interval)
- filename = f"{filename_base}_{i + 1}.png"
- self.player.video_take_snapshot(0, filename, 0, 0)
- messagebox.showinfo("Capturing Screenshots", f"Captured {num_screenshots} screenshots every {interval} seconds to {filename_base}")
- def copy_to_clipboard(self):
- channel = self.channel_var.get()
- if channel and channel in self.channels:
- url = self.channels[channel]
- self.root.clipboard_clear()
- self.root.clipboard_append(url)
- messagebox.showinfo("Copied", f"URL copied to clipboard: {url}")
- else:
- messagebox.showerror("Error", "No channel selected or invalid channel.")
- if __name__ == "__main__":
- root = tk.Tk()
- app = ChannelPlayer(root)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement