pyqt 播放视频遮罩显示 时钟

windows 可以实现 字幕,时钟,全屏加载图片。

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())
相关推荐
ulimate_2 小时前
树莓派无法播放哔哩哔哩等视频
音视频
DogDaoDao5 小时前
DCT与DST变换原理及其在音视频编码中的应用解析
音视频·实时音视频·视频编解码·dct变换·变换编码·dst变换
PythonFun5 小时前
从零开始,用WPS和DeepSeek打造数字人科普视频
音视频·wps
Dxy123931021611 小时前
python如何通过链接下载保存视频
python·spring·音视频
东风西巷11 小时前
K-Lite Mega/FULL Codec Pack(视频解码器)
前端·电脑·音视频·软件需求
爱吃牛肉的大老虎1 天前
FFmpeg和ZLMediaKit 实现本地视频推流
ffmpeg·音视频
wwwzhouhui1 天前
85-dify案例分享-不用等 OpenAI 邀请,Dify+Sora2工作流实测:写实动漫视频随手做,插件+教程全送
人工智能·音视频·sora2
SongYuLong的博客2 天前
ubuntu24.04 实现DLNA音频推送
音视频
浮生如梦_2 天前
图片转视频
图像处理·人工智能·计算机视觉·音视频