python
复制代码
# coding=utf-8
import glob
import sys
import os
import subprocess
current_dir = os.path.dirname(os.path.abspath(__file__))
paths = [current_dir, current_dir + '/../']
for path in paths:
sys.path.insert(0, path)
os.environ['PYTHONPATH'] = (os.environ.get('PYTHONPATH', '') + ':' + path).strip(':')
import sys
import os
import time
import subprocess
import threading
from PyQt5.QtWidgets import QApplication, QLabel, QWidget
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QObject
from PyQt5.QtGui import QFont, QPixmap
from tool_pic.pil_resize import load_img_path
class TransparentSubtitle(QWidget):
"""透明字幕覆盖窗口(支持滚动)"""
def __init__(self, text="Hello, World!", scroll=False):
super().__init__()
self.scroll = scroll
self.full_text = text
self.offset = 0 # 滚动偏移量
# 窗口属性:透明、置顶、不拦截鼠标事件
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint |
Qt.WindowType.WindowStaysOnTopHint |
Qt.WindowType.X11BypassWindowManagerHint
)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground, True)
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, True)
# 字幕标签
self.label = QLabel(self)
self.label.setFont(QFont("Microsoft YaHei", 28, QFont.Weight.Bold))
self.label.setStyleSheet("color: yellow; background-color: rgba(0,0,0,80); padding: 5px; border-radius: 8px;")
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
# 窗口大小 & 位置(底部居中)
screen = QApplication.primaryScreen().availableGeometry()
self.resize(screen.width(), 80)
self.move(0, screen.height() - 120)
# 定时器
self.timer = QTimer()
self.timer.timeout.connect(self.update_subtitle)
if self.scroll:
self.timer.start(200) # 滚动速度
else:
self.set_text(self.full_text)
self.show()
def set_text(self, text):
"""设置字幕文本"""
self.full_text = text
self.label.setText(text)
self.label.adjustSize()
self.label.move((self.width() - self.label.width()) // 2,
(self.height() - self.label.height()) // 2)
def update_subtitle(self):
"""滚动字幕"""
if self.scroll:
# 截取部分文本实现滚动
display_len = 20 # 显示长度
show_text = self.full_text[self.offset:self.offset + display_len]
if len(show_text) < display_len:
# 循环拼接
show_text += " " + self.full_text[:display_len - len(show_text)]
self.label.setText(show_text)
self.label.adjustSize()
self.label.move((self.width() - self.label.width()) // 2,
(self.height() - self.label.height()) // 2)
self.offset = (self.offset + 1) % len(self.full_text)
def show_text(self):
"""外部调用:显示字幕"""
self.show()
def hide_text(self):
"""外部调用:隐藏字幕"""
self.hide()
class TransparentClock(QWidget):
"""右上角透明时钟覆盖"""
def __init__(self):
super().__init__()
self.setWindowFlags(
Qt.WindowType.FramelessWindowHint |
Qt.WindowType.WindowStaysOnTopHint |
Qt.WindowType.Tool
)
self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
self.setAttribute(Qt.WidgetAttribute.WA_NoSystemBackground, True)
self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents, True)
self.label = QLabel(self)
self.label.setFont(QFont("Helvetica", 36, QFont.Weight.Bold))
self.label.setStyleSheet("color: white; background-color: rgba(0,0,0,0);")
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.resize(250, 100)
screen = QApplication.primaryScreen().availableGeometry()
self.move(screen.width() - 300, 50)
self.timer = QTimer()
self.timer.timeout.connect(self.update_time)
self.timer.start(1000)
self.update_time()
self.show()
def update_time(self):
now = time.strftime("%H:%M:%S")
self.label.setText(now)
class VideoWorker(QObject):
"""子线程播放视频"""
finished = pyqtSignal()
def __init__(self, video_path):
super().__init__()
self.video_path = video_path
self._should_stop = False
self.process = None
def play(self):
try:
cmd = ['ffplay', '-i', self.video_path, '-autoexit', '-loglevel', 'quiet', '-volume', '50']
cmd.append('-fs')
self.process = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
creationflags=subprocess.CREATE_NO_WINDOW if os.name == 'nt' else 0)
while not self._should_stop and self.process.poll() is None:
time.sleep(0.01)
if self._should_stop and self.process.poll() is None:
self.process.terminate()
except Exception as e:
print(f"视频播放错误: {e}")
finally:
self.finished.emit()
def stop(self):
self._should_stop = True
if self.process and self.process.poll() is None:
self.process.terminate()
class FullscreenCover(QWidget):
"""全屏封面显示"""
def __init__(self, image_path=None):
super().__init__()
self.setWindowFlags(Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint)
screen = QApplication.primaryScreen().geometry()
self.setGeometry(screen)
self.setStyleSheet("background-color: black;")
self.label = QLabel(self)
self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.label.setStyleSheet("background-color: black;")
self.label.setGeometry(self.rect())
if image_path and os.path.exists(image_path):
pix = QPixmap(image_path)
if pix.isNull():
print("封面加载失败:", image_path)
else:
QTimer.singleShot(50, lambda: self.label.setPixmap(
pix.scaled(self.label.size(), Qt.AspectRatioMode.KeepAspectRatioByExpanding)
))
self.show()
class VideoPlayerApp(QApplication):
"""全屏视频播放器"""
def __init__(self, videos, cover_path=None):
super().__init__(sys.argv)
self.videos = videos
self.current_index = 0
# 全屏封面
self.cover = None
if cover_path:
self.cover = FullscreenCover(cover_path)
# 时钟覆盖
self.clock = TransparentClock()
self.subtitle = TransparentSubtitle("这是滚动字幕示例:麒麟系统 PyQt5 全屏字幕测试", scroll=False)
# 播放第一个视频
self.play_next_video()
def play_next_video(self):
if self.current_index >= len(self.videos):
print("所有视频播放完成")
self.quit()
return
video_path = self.videos[self.current_index]
print("播放视频:", video_path)
# Worker
self.worker = VideoWorker(video_path)
self.worker.finished.connect(self.on_video_finished)
# 启动线程播放
self.thread = threading.Thread(target=self.worker.play, daemon=True)
self.thread.start()
# 定时检查视频是否启动,隐藏封面
self.check_timer = QTimer()
self.check_timer.timeout.connect(self.check_video_started)
self.check_timer.start(50)
def check_video_started(self):
if self.worker.process and self.worker.process.poll() is None:
time.sleep(2)
if self.cover:
self.cover.hide()
# self.check_timer.stop()
def on_video_finished(self):
print("视频播放结束")
self.current_index += 1
self.clock.hide()
self.play_next_video()
def stop_current_video(self):
if hasattr(self, "worker") and self.worker:
self.worker.stop()
if self.cover:
self.cover.hide()
self.clock.hide()
if __name__ == "__main__":
cover_path = load_img_path
if sys.platform == "win32":
videos = [r"C:\Users\Administrator\Videos\f7.mp4"]
else:
videos = ["/home/yklele/video/aa.mp4"]
app = VideoPlayerApp(videos, cover_path)
sys.exit(app.exec())