0% found this document useful (0 votes)
32 views9 pages

Python VLC Video Player App

Basic video player with python

Uploaded by

onbogor
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
32 views9 pages

Python VLC Video Player App

Basic video player with python

Uploaded by

onbogor
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

import sys

import os
import configparser
import keyboard
from [Link] import (QApplication, QMainWindow, QWidget, QLabel,
QPushButton, QVBoxLayout, QHBoxLayout, QFrame,
QColorDialog, QRadioButton, QButtonGroup,
QScrollArea)
from [Link] import Qt, QTimer
from [Link] import QColor, QFont
import vlc

class OverlayWindow(QWidget):
def __init__(self):
super().__init__()
[Link]([Link] | [Link] |
[Link])
[Link](Qt.WA_TranslucentBackground)

# Inisialisasi Label Cover


self.cover_atas = QLabel(self)
self.cover_bawah = QLabel(self)
self.cover_kiri = QLabel(self)
self.cover_kanan = QLabel(self)

# Guide untuk debugging


self.video_guide = QFrame(self)
self.video_guide.setStyleSheet("border: 2px solid #00FF00;")
self.guide_atas = QFrame(self)
self.guide_atas.setStyleSheet("border: 1px solid #FF0000;")
self.guide_bawah = QFrame(self)
self.guide_bawah.setStyleSheet("border: 1px solid #0000FF;")
self.guide_kiri = QFrame(self)
self.guide_kiri.setStyleSheet("border: 1px solid #FFFF00;")
self.guide_kanan = QFrame(self)
self.guide_kanan.setStyleSheet("border: 1px solid #FF00FF;")

self.text_label = QLabel(self)
self.text_label.hide()

# Sembunyikan semua guide di awal


for g in [self.video_guide, self.guide_atas, self.guide_bawah,
self.guide_kiri, self.guide_kanan]:
[Link]()

[Link]()

class VideoPlayerApp(QMainWindow):
def __init__(self):
super().__init__()
self.config_file = "[Link]"
self.video_dir = [Link]([Link](), "video")
self.video_list = sorted([f for f in [Link](self.video_dir) if
[Link]('.mp4')])
self.current_index = 0
[Link] = 10
self.is_debugging = False

self.load_config()
self.setup_vlc_instance()

[Link]([Link] | [Link])
[Link]("background-color: black;")
self.video_frame = QFrame(self)

if [Link] == "win32":
[Link].set_hwnd(int(self.video_frame.winId()))

[Link] = OverlayWindow()
[Link]()
self.apply_changes()
self.init_nav_ui()

keyboard.add_hotkey('a', lambda: [Link](0,


self.play_custom_next))
keyboard.add_hotkey('b', lambda: [Link](0, self.play_intro))
keyboard.add_hotkey('d', lambda: [Link](0, self.toggle_nav))

self.monitor_timer = QTimer()
self.monitor_timer.[Link](self.update_logic_tick)
self.monitor_timer.start(500)

[Link](500, self.play_intro)

def setup_vlc_instance(self):
args = ["--no-xlib", "--quiet", "--no-video-title-show"]
rotation_map = {90: "90", 180: "180", 270: "270"}
if self.video_rotation in rotation_map:
[Link]("--video-filter=transform")
[Link](f"--transform-type={rotation_map[self.video_rotation]}")

[Link] = [Link](args)
[Link] = [Link].media_player_new()

def load_config(self):
[Link] = [Link](allow_no_value=True)
self.header_text = ";
==========================================================================\n;
DOKUMENTASI KONFIGURASI VIDEO PLAYER\n;
==========================================================================\n"

if not [Link](self.config_file):
with open(self.config_file, 'w') as f:
[Link](self.header_text)
[Link]("[myPlayer]\nx = 0\ny = 0\nwidth = 1920\nrotation =
0\n\n")
[Link]("[cover]\natasHeight = 200\nfadingAtasHeight =
100\ncolorAtas = #550000\nrotAtas = 0\n"
"bawahHeight = 200\nfadingBawahHeight = 100\ncolorBawah
= #00ff00\nrotBawah = 0\n"
"kiriWidth = 200\nfadingKiriWidth = 100\ncolorKiri =
#0000ff\nrotKiri = 0\n"
"kananWidth = 200\nfadingKananWidth = 100\ncolorKanan =
#ff00ff\nrotKanan = 0\n\n")
# Default video data omitted for brevity, logic remains same

[Link](self.config_file)
# Player settings
self.player_x = [Link]('myPlayer', 'x', fallback=0.0)
self.player_y = [Link]('myPlayer', 'y', fallback=0.0)
self.player_w = [Link]('myPlayer', 'width',
fallback=1920.0)
self.video_rotation = [Link]('myPlayer', 'rotation',
fallback=0)

# Cover settings
c = 'cover'
self.cover_atas_height = [Link](c, 'atasHeight',
fallback=200.0)
self.fading_atas_height = [Link](c, 'fadingAtasHeight',
fallback=100.0)
self.color_atas = [Link](c, 'colorAtas', fallback="#550000")
self.rot_atas = [Link](c, 'rotAtas', fallback=0)

self.cover_bawah_height = [Link](c, 'bawahHeight',


fallback=200.0)
self.fading_bawah_height = [Link](c, 'fadingBawahHeight',
fallback=100.0)
self.color_bawah = [Link](c, 'colorBawah', fallback="#00ff00")
self.rot_bawah = [Link](c, 'rotBawah', fallback=0)

self.cover_kiri_width = [Link](c, 'kiriWidth',


fallback=200.0)
self.fading_kiri_width = [Link](c, 'fadingKiriWidth',
fallback=100.0)
self.color_kiri = [Link](c, 'colorKiri', fallback="#0000ff")
self.rot_kiri = [Link](c, 'rotKiri', fallback=0)

self.cover_kanan_width = [Link](c, 'kananWidth',


fallback=200.0)
self.fading_kanan_width = [Link](c, 'fadingKananWidth',
fallback=100.0)
self.color_kanan = [Link](c, 'colorKanan', fallback="#ff00ff")
self.rot_kanan = [Link](c, 'rotKanan', fallback=0)

def save_config(self):
if 'myPlayer' not in [Link]: [Link]['myPlayer'] = {}
[Link]['myPlayer'].update({
'x': str(self.player_x), 'y': str(self.player_y), 'width':
str(self.player_w), 'rotation': str(self.video_rotation)
})
if 'cover' not in [Link]: [Link]['cover'] = {}
[Link]['cover'].update({
'atasHeight': str(self.cover_atas_height), 'fadingAtasHeight':
str(self.fading_atas_height), 'colorAtas': self.color_atas, 'rotAtas':
str(self.rot_atas),
'bawahHeight': str(self.cover_bawah_height), 'fadingBawahHeight':
str(self.fading_bawah_height), 'colorBawah': self.color_bawah, 'rotBawah':
str(self.rot_bawah),
'kiriWidth': str(self.cover_kiri_width), 'fadingKiriWidth':
str(self.fading_kiri_width), 'colorKiri': self.color_kiri, 'rotKiri':
str(self.rot_kiri),
'kananWidth': str(self.cover_kanan_width), 'fadingKananWidth':
str(self.fading_kanan_width), 'colorKanan': self.color_kanan, 'rotKanan':
str(self.rot_kanan)
})
with open(self.config_file, 'w') as f:
[Link](self.header_text)
[Link](f)

def rotate_logic(self, target):


rotations = [0, 90, 180, 270]
if target == 'video':
curr_idx = [Link](self.video_rotation)
self.video_rotation = rotations[(curr_idx + 1) % len(rotations)]
curr_time = [Link].get_time()
[Link]()
self.setup_vlc_instance()
if [Link] == "win32":
[Link].set_hwnd(int(self.video_frame.winId()))
self.play_video(self.current_index)
[Link].set_time(curr_time)
else:
attr = f"rot_{target}"
curr_val = getattr(self, attr)
curr_idx = [Link](curr_val)
setattr(self, attr, rotations[(curr_idx + 1) % len(rotations)])

self.apply_changes()
self.update_nav_labels()

def get_gradient(self, side, color_hex, total, fading, rotation):


c = QColor(color_hex)
r, g, b = [Link](), [Link](), [Link]()
# Perhitungan stop gradient
val = (fading / total) if total > 0 else 0.5
stop = max(0.0, min(1.0, val))

# Mapping arah gradient berdasarkan rotasi visual


# Default (0) Atas: Top->Bottom, Bawah: Bottom->Top, Kiri: Left->Right,
Kanan: Right->Left
dirs = {
'atas': ("x1:0, y1:0, x2:0, y2:1", f"stop:0 {color_hex},
stop:{1.0-stop:.2f} {color_hex}, stop:1 rgba({r},{g},{b},0)"),
'bawah': ("x1:0, y1:0, x2:0, y2:1", f"stop:0 rgba({r},{g},{b},0),
stop:{stop:.2f} {color_hex}, stop:1 {color_hex}"),
'kiri': ("x1:0, y1:0, x2:1, y2:0", f"stop:0 {color_hex},
stop:{1.0-stop:.2f} {color_hex}, stop:1 rgba({r},{g},{b},0)"),
'kanan': ("x1:0, y1:0, x2:1, y2:0", f"stop:0 rgba({r},{g},{b},0),
stop:{stop:.2f} {color_hex}, stop:1 {color_hex}")
}

# Catatan: Rotasi disini merubah arah gradient relatif terhadap box-nya


# Jika rotasi 180, gradient dibalik
style = f"background-color: qlineargradient({dirs[side][0]},
{dirs[side][1]});"
if rotation != 0:
style += f" border: none; transform: rotate({rotation}deg);"
return style

def apply_changes(self):
sw, sh = [Link]().size().width(),
[Link]().size().height()
self.video_frame.setGeometry(int(self.player_x), int(self.player_y),
int(self.player_w), sh)

# Update Geometries
[Link].cover_atas.setGeometry(0, 0, sw,
int(self.cover_atas_height))
[Link].cover_bawah.setGeometry(0, sh -
int(self.cover_bawah_height), sw, int(self.cover_bawah_height))
[Link].cover_kiri.setGeometry(0, 0, int(self.cover_kiri_width),
sh)
[Link].cover_kanan.setGeometry(sw - int(self.cover_kanan_width),
0, int(self.cover_kanan_width), sh)

# Apply Styles & Gradients


[Link].cover_atas.setStyleSheet(self.get_gradient('atas',
self.color_atas, self.cover_atas_height, self.fading_atas_height,
self.rot_atas))
[Link].cover_bawah.setStyleSheet(self.get_gradient('bawah',
self.color_bawah, self.cover_bawah_height, self.fading_bawah_height,
self.rot_bawah))
[Link].cover_kiri.setStyleSheet(self.get_gradient('kiri',
self.color_kiri, self.cover_kiri_width, self.fading_kiri_width, self.rot_kiri))
[Link].cover_kanan.setStyleSheet(self.get_gradient('kanan',
self.color_kanan, self.cover_kanan_width, self.fading_kanan_width,
self.rot_kanan))

if self.is_debugging:
[Link].video_guide.setGeometry(self.video_frame.geometry())

[Link].guide_atas.setGeometry([Link].cover_atas.geometry())

[Link].guide_bawah.setGeometry([Link].cover_bawah.geometry())

[Link].guide_kiri.setGeometry([Link].cover_kiri.geometry())

[Link].guide_kanan.setGeometry([Link].cover_kanan.geometry())
for g in [[Link].video_guide, [Link].guide_atas,
[Link].guide_bawah, [Link].guide_kiri, [Link].guide_kanan]:
[Link]()
else:
for g in [[Link].video_guide, [Link].guide_atas,
[Link].guide_bawah, [Link].guide_kiri, [Link].guide_kanan]:
[Link]()

def init_nav_ui(self):
self.nav_window = QWidget()
self.nav_window.setWindowTitle("Panel Kontrol")
self.nav_window.setWindowFlags([Link] | [Link])
self.nav_window.setFixedSize(500, 850)

main_layout = QVBoxLayout()
scroll = QScrollArea()
[Link](True)
content_widget = QWidget()
layout = QVBoxLayout(content_widget)

# Step Selection
step_layout = QHBoxLayout()
self.radio01, self.radio1, self.radio10 = QRadioButton("0.1 px"),
QRadioButton("1 px"), QRadioButton("10 px")
[Link](True)
self.radio_group = QButtonGroup()
for r in [self.radio01, self.radio1, self.radio10]:
self.radio_group.addButton(r); step_layout.addWidget(r)
[Link](lambda: setattr(self, 'step', 0.1))
[Link](lambda: setattr(self, 'step', 1))
[Link](lambda: setattr(self, 'step', 10))
[Link](step_layout)

# Global Video Controls


v_rot_layout = QHBoxLayout()
btn_v_rot = QPushButton("Rotate Video 90°")
btn_v_rot.[Link](lambda: self.rotate_logic('video'))
self.lbl_v_rot = QLabel("0°")
v_rot_layout.addWidget(btn_v_rot);
v_rot_layout.addWidget(self.lbl_v_rot)
[Link](v_rot_layout)

[Link] = {}
# Param: (Display Name, Attribute Name, Type['color','rot','val'],
TargetKey)
controls = [
("X-Video", "player_x", "val"), ("Y-Video", "player_y", "val"),
("W-Video", "player_w", "val"),
("--- ATAS ---", None, "sep"), ("H-Atas", "cover_atas_height",
"val"), ("F-Atas", "fading_atas_height", "val"), ("Warna Atas", "color_atas",
"color", "atas"), ("Rot Atas", "rot_atas", "rot", "atas"),
("--- BAWAH ---", None, "sep"), ("H-Bawah", "cover_bawah_height",
"val"), ("F-Bawah", "fading_bawah_height", "val"), ("Warna Bawah",
"color_bawah", "color", "bawah"), ("Rot Bawah", "rot_bawah", "rot", "bawah"),
("--- KIRI ---", None, "sep"), ("W-Kiri", "cover_kiri_width",
"val"), ("F-Kiri", "fading_kiri_width", "val"), ("Warna Kiri", "color_kiri",
"color", "kiri"), ("Rot Kiri", "rot_kiri", "rot", "kiri"),
("--- KANAN ---", None, "sep"), ("W-Kanan", "cover_kanan_width",
"val"), ("F-Kanan", "fading_kanan_width", "val"), ("Warna Kanan", "color_kanan",
"color", "kanan"), ("Rot Kanan", "rot_kanan", "rot", "kanan")
]

for name, attr, ctype, *extra in controls:


if ctype == "sep":
lbl = QLabel(name); [Link]("font-weight: bold;
margin-top: 10px; color: yellow;"); [Link](lbl)
continue
row = QHBoxLayout()
[Link](QLabel(f"{name}:"))
if ctype == "val":
m, p = QPushButton("-"), QPushButton("+")
[Link](lambda ch, a=attr: self.mod_val(a, -1));
[Link](lambda ch, a=attr: self.mod_val(a, 1))
disp = QLabel("0"); [Link][attr] = disp
[Link](m); [Link](p); [Link](disp)
elif ctype == "color":
btn = QPushButton("Pilih Warna")
[Link](lambda ch, t=extra[0]: self.pick_color(t))
[Link](btn)
elif ctype == "rot":
btn = QPushButton("Rot 90°")
[Link](lambda ch, t=extra[0]: self.rotate_logic(t))
disp = QLabel("0°"); [Link][attr] = disp
[Link](btn); [Link](disp)
[Link](row)

[Link](content_widget)
main_layout.addWidget(scroll)
self.nav_window.setLayout(main_layout)

def mod_val(self, attr, direction):


val = getattr(self, attr) + (direction * [Link])
if "fading" in attr:
# Clamp fading agar tidak melebihi total height/width
base = [Link]("fading_", "").replace("Height",
"height").replace("Width", "width")
limit = getattr(self, base, 1000)
val = max(0.0, min(val, limit))
elif any(x in attr for x in ["height", "width"]):
val = max(1.0, val)
setattr(self, attr, round(val, 1)); self.apply_changes();
self.update_nav_labels()

def update_nav_labels(self):
for a, l in [Link]():
val = getattr(self, a)
[Link](f"{val}°" if "rot" in a else f"{val}")
self.lbl_v_rot.setText(f"{self.video_rotation}°")

def toggle_nav(self):
if self.nav_window.isVisible(): self.is_debugging = False;
self.nav_window.hide()
else: self.is_debugging = True; self.nav_window.show();
self.update_nav_labels()
self.apply_changes()

def pick_color(self, target):


attr = f"color_{target}"
current = getattr(self, attr)
color = [Link](QColor(current), self, f"Warna {target}")
if [Link]():
setattr(self, attr, [Link]())
self.apply_changes()

def update_logic_tick(self):
if not [Link].is_playing():
if [Link].get_state() == [Link]:
self.handle_navigation_logic()
return
curr_ms, total_ms = [Link].get_time(), [Link].get_length()
if total_ms > 0:
rem_pct = 100 - ((curr_ms / total_ms) * 100)
conf = [Link][f'video_{self.current_index}']
if [Link]('text_enable', fallback=False):
trigger, duration = float([Link]('text_trigger_pct', 10)),
float([Link]('text_duration_pct', 5))
if trigger >= rem_pct >= (trigger - duration):
self.show_overlay_text(conf)
else: [Link].text_label.hide()

def show_overlay_text(self, conf):


lbl = [Link].text_label
[Link]([Link]('text_content').replace('\\n', '\n'))
[Link]([Link])
[Link](f"background-color: {[Link]('text_bg')}; color:
{[Link]('text_color')}; font-size: {[Link]('text_size')}px; padding: 20px;
border-radius: 10px;")
[Link]([Link]('text_x'), [Link]('text_y'))
[Link](); [Link]()

def handle_navigation_logic(self):
conf = [Link][f'video_{self.current_index}']
mode = [Link]('mode', 'stop').lower()
if mode == 'loop': self.play_video(self.current_index)
elif mode == 'autonext':
next_idx = self.current_index + 1
if f'video_{next_idx}' in [Link]: self.play_video(next_idx)
else: [Link]()
else: [Link]()

def play_custom_next(self):
conf = [Link][f'video_{self.current_index}']
target_idx = [Link]('next_index', fallback=0)
if target_idx == 0 and self.current_index != 0: return
if f'video_{target_idx}' in [Link]: self.play_video(target_idx)

def play_video(self, idx):


self.current_index = idx
if f'video_{idx}' not in [Link]: return
path = [Link](self.video_dir, [Link](f"video_{idx}",
'filename'))
if [Link](path):
m = [Link].media_new(path)
[Link].set_media(m); [Link]()
self.apply_changes()

def play_intro(self): self.play_video(0)


def keyPressEvent(self, e):
if [Link]() == Qt.Key_Escape:
self.save_config(); [Link](); keyboard.unhook_all();
[Link]()

if __name__ == '__main__':
app = QApplication([Link])
if not [Link]("video"): [Link]("video")
ex = VideoPlayerApp()
[Link](app.exec_())

You might also like