Không có tiêu đề

import tkinter as tk from tkinter import messagebox, ttk import vlc import time class CustomSlider(tk.Canvas): def __init__(self, master, **kwargs): super().__init__(master, **kwargs) self.bind("", self.on_click) self.value = 0 self.command = None def set(self, value): self.value = value self.update() def update(self): self.delete("all") width = self.winfo_width() height = self.winfo_height() filled_width = int(self.value * width / 100) self.create_rectangle(0, 0, width, height, fill="grey", outline="") self.create_rectangle(0, 0, filled_width, height, fill="green", outline="") def on_click(self, event): width = self.winfo_width() click_position = event.x / width self.value = int(click_position * 100) self.update() if self.command: self.command(self.value) class PlaylistWindow(tk.Toplevel): def __init__(self, master, playlist, play_function): super().__init__(master) self.title("Playlist") self.geometry("300x400") self.protocol("WM_DELETE_WINDOW", self.hide_window) self.listbox = tk.Listbox(self) self.listbox.pack(fill=tk.BOTH, expand=True) for item in playlist: self.listbox.insert(tk.END, item['name']) # Thay đổi từ double-click sang single-click self.listbox.bind('', lambda e: play_function(self.listbox.curselection()[0])) # Thêm nút "Play Selected" self.play_button = tk.Button(self, text="Play Selected", command=self.play_selected) self.play_button.pack(fill=tk.X) self.play_function = play_function def play_selected(self): selection = self.listbox.curselection() if selection: self.play_function(selection[0]) def hide_window(self): self.withdraw() class VideoPlayer(tk.Tk): def __init__(self, playlist): super().__init__() # Thêm biến playlist và chỉ mục hiện tại self.playlist = playlist self.current_index = 0 # Cài đặt kích thước giao diện self.title("M3U8 Video Player") self.geometry("900x650") # Biến để kiểm tra trạng thái toàn màn hình self.fullscreen = False # Tạo một frame để hiển thị video self.video_frame = tk.Frame(self, bg='black') self.video_frame.pack(fill=tk.BOTH, expand=1) # Khởi tạo trình phát video VLC self.instance = vlc.Instance("--sub-source=marq") self.player = self.instance.media_player_new() # Lấy handle của frame để nhúng video self.player.set_hwnd(self.video_frame.winfo_id()) # Khởi tạo video đầu tiên self.load_video(self.playlist[self.current_index]['url'], self.playlist[self.current_index].get('subtitle')) # Tự động phát video khi khởi động self.after(1000, self.auto_start_playback) # Thêm nút điều khiển và thanh thời gian self.control_frame = tk.Frame(self) self.control_frame.pack(side=tk.BOTTOM, fill=tk.X) self.play_pause_button = tk.Button(self.control_frame, text="Play", command=self.toggle_play_pause) self.play_pause_button.pack(side=tk.LEFT) # Thanh thời gian tùy chỉnh self.time_slider = CustomSlider(self.control_frame, height=20) self.time_slider.pack(side=tk.LEFT, fill=tk.X, expand=1) self.time_slider.command = self.seek_to_time # Hiển thị thời gian hiện tại và tổng thời gian self.current_time_label = tk.Label(self.control_frame, text="00:00:00") self.current_time_label.pack(side=tk.LEFT) self.total_time_label = tk.Label(self.control_frame, text="00:00:00") self.total_time_label.pack(side=tk.LEFT) # Điều khiển âm lượng self.volume_slider = tk.Scale(self.control_frame, from_=0, to=100, orient=tk.HORIZONTAL, command=self.set_volume) self.volume_slider.set(100) # Đặt âm lượng mặc định là 100% self.volume_slider.pack(side=tk.LEFT) # Nút toàn màn hình fullscreen_button = tk.Button(self.control_frame, text="Toàn màn hình", command=self.toggle_fullscreen) fullscreen_button.pack(side=tk.LEFT) # Thêm nút chuyển bài next_button = tk.Button(self.control_frame, text="Next", command=self.next_video) next_button.pack(side=tk.LEFT) prev_button = tk.Button(self.control_frame, text="Previous", command=self.prev_video) prev_button.pack(side=tk.LEFT) # Thêm nút Playlist self.playlist_button = tk.Button(self.control_frame, text="Playlist", command=self.toggle_playlist_window) self.playlist_button.pack(side=tk.LEFT) # Tạo cửa sổ playlist (ban đầu là ẩn) self.playlist_window = PlaylistWindow(self, playlist, self.play_from_playlist) self.playlist_window.withdraw() # Bắt đầu cập nhật thời gian self.update_time() # Bắt sự kiện tương tác chuột và bàn phím self.bind("", self.show_controls) self.bind("", self.show_controls) # Timer để ẩn giao diện khi không tương tác self.hide_controls_timer = None # Thêm binding cho các phím tắt self.bind("", lambda e: self.toggle_play_pause()) self.bind("", lambda e: self.seek(-5)) self.bind("", lambda e: self.seek(5)) self.bind("", lambda e: self.change_volume(5)) self.bind("", lambda e: self.change_volume(-5)) # Thêm binding cho phím Esc self.bind("", self.exit_fullscreen) def auto_start_playback(self): self.play() self.play_pause_button.config(text="Pause") def play(self): self.player.play() self.play_pause_button.config(text="Pause") def pause(self): self.player.pause() self.play_pause_button.config(text="Play") def seek(self, seconds): current_time = self.player.get_time() new_time = current_time + seconds * 1000 # Chuyển đổi giây sang mili giây self.player.set_time(new_time) def seek_to_time(self, value): total_length = self.player.get_length() new_time = int(value) * total_length / 100 self.player.set_time(int(new_time)) def set_volume(self, value): self.player.audio_set_volume(int(value)) def change_volume(self, delta): current_volume = self.player.audio_get_volume() new_volume = max(0, min(100, current_volume + delta)) self.player.audio_set_volume(new_volume) self.volume_slider.set(new_volume) def toggle_play_pause(self, event=None): if self.player.is_playing(): self.pause() else: self.play() def toggle_fullscreen(self): self.fullscreen = not self.fullscreen if self.fullscreen: self.attributes("-fullscreen", True) self.control_frame.pack_forget() # Ẩn control frame else: self.exit_fullscreen() def exit_fullscreen(self, event=None): if self.fullscreen: self.fullscreen = False self.attributes("-fullscreen", False) self.control_frame.pack(side=tk.BOTTOM, fill=tk.X) # Hiện lại control frame def update_time(self): if self.player.is_playing(): current_time = self.player.get_time() total_length = self.player.get_length() # Cập nhật thanh trượt thời gian if total_length > 0: slider_value = int(current_time * 100 / total_length) self.time_slider.set(slider_value) # Cập nhật hiển thị thời gian current_time_str = self.format_time(current_time) total_time_str = self.format_time(total_length) self.current_time_label.config(text=current_time_str) self.total_time_label.config(text=total_time_str) self.after(100, self.update_time) def format_time(self, milliseconds): seconds, milliseconds = divmod(milliseconds, 1000) minutes, seconds = divmod(seconds, 60) hours, minutes = divmod(minutes, 60) return "{:02d}:{:02d}:{:02d}".format(int(hours), int(minutes), int(seconds)) def show_controls(self, event): if self.fullscreen: self.control_frame.pack(side=tk.BOTTOM, fill=tk.X) if self.hide_controls_timer: self.after_cancel(self.hide_controls_timer) self.hide_controls_timer = self.after(2000, self.hide_controls) def hide_controls(self): if self.fullscreen: self.control_frame.pack_forget() def load_video(self, url, subtitle_url=None): media = self.instance.media_new(url) if subtitle_url: media.add_option(f'sub-file={subtitle_url}') self.player.set_media(media) self.update_title() def update_title(self): current_video = self.playlist[self.current_index] self.title(f"Now Playing: {current_video['name']}") def toggle_playlist_window(self): if self.playlist_window.winfo_viewable(): self.playlist_window.hide_window() else: self.playlist_window.deiconify() def play_from_playlist(self, index): if 0 <= index < len(self.playlist): self.current_index = index current_item = self.playlist[self.current_index] self.load_video(current_item['url'], current_item.get('subtitle')) self.play() self.playlist_window.listbox.selection_clear(0, tk.END) self.playlist_window.listbox.selection_set(self.current_index) self.playlist_window.listbox.see(self.current_index) # Đảm bảo mục được chọn luôn hiển thị def next_video(self): self.current_index = (self.current_index + 1) % len(self.playlist) current_item = self.playlist[self.current_index] self.load_video(current_item['url'], current_item.get('subtitle')) self.play() self.playlist_window.listbox.selection_clear(0, tk.END) self.playlist_window.listbox.selection_set(self.current_index) self.playlist_window.listbox.see(self.current_index) def prev_video(self): self.current_index = (self.current_index - 1) % len(self.playlist) current_item = self.playlist[self.current_index] self.load_video(current_item['url'], current_item.get('subtitle')) self.play() self.playlist_window.listbox.selection_clear(0, tk.END) self.playlist_window.listbox.selection_set(self.current_index) self.playlist_window.listbox.see(self.current_index) def on_closing(self): self.player.stop() self.destroy() if __name__ == "__main__": playlist = [ { "name": "Spy x Family Episode 1", "url": "https://raw.githubusercontent.com/Huyenuiio/gittesst2/spyxfamily/spyxfamilycodewhite/output.m3u8", "subtitle": "path/to/spyxfamily_ep1_subtitle.ass" }, { "name": "Another Episode", "url": "https://raw.githubusercontent.com/Huyenuiio/fsfafafewwkjawekfj/main/ep1/output.m3u8", "subtitle": "./ff.ass" }, # Thêm các mục khác vào đây ] app = VideoPlayer(playlist) app.protocol("WM_DELETE_WINDOW", app.on_closing) app.mainloop()
Huyền

Một Blog Anime chia sẻ những bộ anime hay download về để xem chất lượng cao nhất. neyuhv.blogspot.com does not host any files, it merely links to 3rd party services. Legal issues should be taken up with the file hosts and providers. neyuhv.blogspot.com is not responsible for any media files shown by the video providers.

Mới hơn Cũ hơn