def __init__(self, id, volume, cacheFolder, top=False, title='', resize=[], textSetting=[True, 20, 2, 6, 0, '【 [ {'], maxCacheSize=2048000, startWithDanmu=True): super(VideoWidget, self).__init__() self.setAcceptDrops(True) self.installEventFilter(self) self.id = id self.title = '未定义的直播间' self.uname = '未定义' self.hoverToken = False self.roomID = '0' # 初始化直播间房号 self.liveStatus = 0 # 初始化直播状态为0 self.pauseToken = False self.quality = 250 self.audioChannel = 0 # 0 原始音效 5 杜比音效 self.volume = volume self.volumeAmplify = 1.0 # 音量加倍 self.hardwareDecode = True self.leftButtonPress = False self.rightButtonPress = False self.fullScreen = False self.userPause = False # 用户暂停 self.cacheName = '' self.maxCacheSize = maxCacheSize self.startWithDanmu = startWithDanmu self.setFrameShape(QFrame.Box) self.setObjectName('video') self.top = top if top: # 悬浮窗取消关闭按钮 vlc版点关闭后有bug 让用户右键退出 self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint) else: self.setStyleSheet( '#video{border-width:1px;border-style:solid;border-color:gray}' ) self.textSetting = textSetting self.horiPercent = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][self.textSetting[2]] self.vertPercent = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][self.textSetting[3]] self.filters = textSetting[5].split(' ') self.opacity = 100 if top: self.setWindowFlag(Qt.WindowStaysOnTopHint) if title: if top: self.setWindowTitle('%s %s' % (title, id + 1 - 9)) else: self.setWindowTitle('%s %s' % (title, id + 1)) if resize: self.resize(resize[0], resize[1]) layout = QGridLayout(self) layout.setContentsMargins(0, 0, 0, 0) self.textBrowser = TextBrowser( self) # 必须赶在resizeEvent和moveEvent之前初始化textbrowser self.setDanmuOpacity(self.textSetting[1]) # 设置弹幕透明度 self.textBrowser.optionWidget.opacitySlider.setValue( self.textSetting[1]) # 设置选项页透明条 self.textBrowser.optionWidget.opacitySlider.value.connect( self.setDanmuOpacity) self.setHorizontalPercent(self.textSetting[2]) # 设置横向占比 self.textBrowser.optionWidget.horizontalCombobox.setCurrentIndex( self.textSetting[2]) # 设置选项页占比框 self.textBrowser.optionWidget.horizontalCombobox.currentIndexChanged.connect( self.setHorizontalPercent) self.setVerticalPercent(self.textSetting[3]) # 设置横向占比 self.textBrowser.optionWidget.verticalCombobox.setCurrentIndex( self.textSetting[3]) # 设置选项页占比框 self.textBrowser.optionWidget.verticalCombobox.currentIndexChanged.connect( self.setVerticalPercent) self.setTranslateBrowser(self.textSetting[4]) self.textBrowser.optionWidget.translateCombobox.setCurrentIndex( self.textSetting[4]) # 设置同传窗口 self.textBrowser.optionWidget.translateCombobox.currentIndexChanged.connect( self.setTranslateBrowser) self.setTranslateFilter(self.textSetting[5]) # 同传过滤字符 self.textBrowser.optionWidget.translateFitler.setText( self.textSetting[5]) self.textBrowser.optionWidget.translateFitler.textChanged.connect( self.setTranslateFilter) self.textBrowser.closeSignal.connect(self.closeDanmu) self.textBrowser.moveSignal.connect(self.moveTextBrowser) if not self.startWithDanmu: # 如果启动隐藏被设置,隐藏弹幕机 self.textSetting[0] = False self.textBrowser.hide() self.textPosDelta = QPoint(0, 0) # 弹幕框和窗口之间的坐标差 self.videoFrame = VideoFrame() # 新版本vlc内核播放器 self.videoFrame.rightClicked.connect(self.rightMouseClicked) self.videoFrame.leftClicked.connect(self.leftMouseClicked) self.videoFrame.doubleClicked.connect(self.doubleClick) layout.addWidget(self.videoFrame, 0, 0, 12, 12) self.instance = vlc.Instance() self.player = self.instance.media_player_new() # 视频播放 self.player.video_set_mouse_input(False) self.player.video_set_key_input(False) if platform.system() == 'Windows': self.player.set_hwnd(self.videoFrame.winId()) elif platform.system() == 'Darwin': # for MacOS self.player.set_nsobject(int(self.videoFrame.winId())) else: self.player.set_xwindow(self.videoFrame.winId()) self.topLabel = QLabel() self.topLabel.setFixedHeight(30) # self.topLabel.setAlignment(Qt.AlignCenter) self.topLabel.setObjectName('frame') self.topLabel.setStyleSheet("background-color:#293038") # self.topLabel.setFixedHeight(32) self.topLabel.setFont(QFont('微软雅黑', 15, QFont.Bold)) layout.addWidget(self.topLabel, 0, 0, 1, 12) self.topLabel.hide() self.frame = QWidget() self.frame.setObjectName('frame') self.frame.setStyleSheet("background-color:#293038") self.frame.setFixedHeight(50) frameLayout = QHBoxLayout(self.frame) frameLayout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.frame, 11, 0, 1, 12) self.frame.hide() self.titleLabel = QLabel() self.titleLabel.setMaximumWidth(150) self.titleLabel.setStyleSheet('background-color:#00000000') self.setTitle() frameLayout.addWidget(self.titleLabel) self.play = PushButton(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.clicked.connect(self.mediaPlay) frameLayout.addWidget(self.play) self.reload = PushButton(self.style().standardIcon( QStyle.SP_BrowserReload)) self.reload.clicked.connect(self.mediaReload) frameLayout.addWidget(self.reload) self.volumeButton = PushButton(self.style().standardIcon( QStyle.SP_MediaVolume)) self.volumeButton.clicked.connect(self.mediaMute) frameLayout.addWidget(self.volumeButton) self.slider = Slider() self.slider.setStyleSheet('background-color:#00000000') self.slider.value.connect(self.setVolume) frameLayout.addWidget(self.slider) self.danmuButton = PushButton(text='弹') self.danmuButton.clicked.connect(self.showDanmu) frameLayout.addWidget(self.danmuButton) self.stop = PushButton(self.style().standardIcon( QStyle.SP_DialogCancelButton)) self.stop.clicked.connect(self.mediaStop) frameLayout.addWidget(self.stop) self.getMediaURL = GetMediaURL(self.id, cacheFolder, maxCacheSize) self.getMediaURL.cacheName.connect(self.setMedia) self.getMediaURL.downloadError.connect(self.mediaReload) self.danmu = remoteThread(self.roomID) self.exportCache = ExportCache() self.exportCache.finish.connect(self.exportFinish) self.exportTip = ExportTip() self.moveTimer = QTimer() self.moveTimer.timeout.connect(self.initTextPos) self.moveTimer.start(50) self.checkPlaying = QTimer() # 检查播放卡住的定时器 self.checkPlaying.timeout.connect(self.checkPlayStatus) logging.info("VLC 播放器构造完毕, 缓存大小: %dkb , 置顶?: %s, 启用弹幕?: %s" % (self.maxCacheSize, self.top, self.startWithDanmu))
def __init__(self, id, volume, cacheFolder, top=False, title='', resize=[], textSetting=[True, 20, 2, 6, 0, '【 [ {', 10], maxCacheSize=2048000, saveCachePath='', startWithDanmu=True, hardwareDecode=True): super(VideoWidget, self).__init__() self.setAcceptDrops(True) self.installEventFilter(self) self.id = id self.title = '' self.uname = '' self.oldTitle = '' self.oldUname = '' self.hoverToken = False self.roomID = '0' # 初始化直播间房号 self.liveStatus = 0 # 初始化直播状态为0 self.pauseToken = False self.quality = 250 self.audioChannel = 0 # 0 原始音效 5 杜比音效 self.volume = volume self.volumeAmplify = 1.0 # 音量加倍 self.muted = False self.hardwareDecode = hardwareDecode self.leftButtonPress = False self.rightButtonPress = False self.fullScreen = False self.userPause = False # 用户暂停 self.cacheName = '' self.maxCacheSize = maxCacheSize self.saveCachePath = saveCachePath self.startWithDanmu = startWithDanmu # 容器设置 self.setFrameShape(QFrame.Box) self.setObjectName('video') self.top = top self.name_str = f"悬浮窗{self.id}" if self.top else f"嵌入窗{self.id}" if top: self.setWindowFlags(Qt.Window) else: self.setStyleSheet( '#video{border-width:1px;border-style:solid;border-color:gray}' ) self.textSetting = textSetting self.horiPercent = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][self.textSetting[2]] self.vertPercent = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0][self.textSetting[3]] self.filters = textSetting[5].split(' ') self.opacity = 100 if top: self.setWindowFlag(Qt.WindowStaysOnTopHint) if title: if top: self.setWindowTitle('%s %s' % (title, id + 1 - 9)) else: self.setWindowTitle('%s %s' % (title, id + 1)) layout = QGridLayout(self) layout.setContentsMargins(0, 0, 0, 0) # ---- 弹幕机 ---- self.textBrowser = TextBrowser( self) # 必须赶在resizeEvent和moveEvent之前初始化textbrowser self.setDanmuOpacity(self.textSetting[1]) # 设置弹幕透明度 self.textBrowser.optionWidget.opacitySlider.setValue( self.textSetting[1]) # 设置选项页透明条 self.textBrowser.optionWidget.opacitySlider.value.connect( self.setDanmuOpacity) self.setHorizontalPercent(self.textSetting[2]) # 设置横向占比 self.textBrowser.optionWidget.horizontalCombobox.setCurrentIndex( self.textSetting[2]) # 设置选项页占比框 self.textBrowser.optionWidget.horizontalCombobox.currentIndexChanged.connect( self.setHorizontalPercent) self.setVerticalPercent(self.textSetting[3]) # 设置横向占比 self.textBrowser.optionWidget.verticalCombobox.setCurrentIndex( self.textSetting[3]) # 设置选项页占比框 self.textBrowser.optionWidget.verticalCombobox.currentIndexChanged.connect( self.setVerticalPercent) self.setTranslateBrowser(self.textSetting[4]) self.textBrowser.optionWidget.translateCombobox.setCurrentIndex( self.textSetting[4]) # 设置同传窗口 self.textBrowser.optionWidget.translateCombobox.currentIndexChanged.connect( self.setTranslateBrowser) self.setTranslateFilter(self.textSetting[5]) # 同传过滤字符 self.textBrowser.optionWidget.translateFitler.setText( self.textSetting[5]) self.textBrowser.optionWidget.translateFitler.textChanged.connect( self.setTranslateFilter) self.setFontSize(self.textSetting[6]) # 设置弹幕字体大小 self.textBrowser.optionWidget.fontSizeCombox.setCurrentIndex( self.textSetting[6]) self.textBrowser.optionWidget.fontSizeCombox.currentIndexChanged.connect( self.setFontSize) self.textBrowser.closeSignal.connect(self.closeDanmu) self.textBrowser.moveSignal.connect(self.moveTextBrowser) if not self.startWithDanmu: # 如果启动隐藏被设置,隐藏弹幕机 self.textSetting[0] = False self.textBrowser.hide() self.textPosDelta = QPoint(0, 0) # 弹幕框和窗口之间的坐标差 self.deltaX = 0 self.deltaY = 0 # ---- 播放器布局设置 ---- # 播放器 self.videoFrame = VideoFrame() # 新版本vlc内核播放器 self.videoFrame.rightClicked.connect(self.rightMouseClicked) self.videoFrame.leftClicked.connect(self.leftMouseClicked) self.videoFrame.doubleClicked.connect(self.doubleClick) layout.addWidget(self.videoFrame, 0, 0, 12, 12) # vlc 实例 self.instance = vlc.Instance() self.newPlayer() # 实例化 player # 直播间标题 self.topLabel = QLabel() self.topLabel.setFixedHeight(30) # self.topLabel.setAlignment(Qt.AlignCenter) self.topLabel.setObjectName('frame') self.topLabel.setStyleSheet("background-color:#293038") # self.topLabel.setFixedHeight(32) self.topLabel.setFont(QFont('微软雅黑', 15, QFont.Bold)) layout.addWidget(self.topLabel, 0, 0, 1, 12) self.topLabel.hide() # 控制栏容器 self.frame = QWidget() self.frame.setObjectName('frame') self.frame.setStyleSheet("background-color:#293038") self.frame.setFixedHeight(50) frameLayout = QHBoxLayout(self.frame) frameLayout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.frame, 11, 0, 1, 12) self.frame.hide() # ---- 嵌入式播放器 控制栏 ---- # 主播名 self.titleLabel = QLabel() self.titleLabel.setMaximumWidth(150) self.titleLabel.setStyleSheet('background-color:#00000000') self.setTitle() frameLayout.addWidget(self.titleLabel) # 播放/暂停 self.play = PushButton(self.style().standardIcon(QStyle.SP_MediaPause)) self.play.clicked.connect(self.mediaPlay) frameLayout.addWidget(self.play) # 刷新 self.reload = PushButton(self.style().standardIcon( QStyle.SP_BrowserReload)) self.reload.clicked.connect(self.mediaReload) frameLayout.addWidget(self.reload) # 音量开关 self.volumeButton = PushButton(self.style().standardIcon( QStyle.SP_MediaVolume)) self.volumeButton.clicked.connect(self.mediaMute) frameLayout.addWidget(self.volumeButton) # 音量滑条 self.slider = Slider() self.slider.setStyleSheet('background-color:#00000000') self.slider.value.connect(self.setVolume) frameLayout.addWidget(self.slider) # 弹幕开关 self.danmuButton = PushButton(text='弹') self.danmuButton.clicked.connect(self.showDanmu) frameLayout.addWidget(self.danmuButton) # 关闭窗口 self.stop = PushButton(self.style().standardIcon( QStyle.SP_DialogCancelButton)) self.stop.clicked.connect(self.mediaStop) frameLayout.addWidget(self.stop) # ---- IO 交互设置 ---- # 单开线程获取视频流 self.getMediaURL = GetMediaURL(self.id, cacheFolder, maxCacheSize, saveCachePath) self.getMediaURL.cacheName.connect(self.setMedia) self.getMediaURL.copyFile.connect(self.copyCache) self.getMediaURL.downloadError.connect(self.mediaReload) self.danmu = remoteThread(self.roomID) # 导出配置 self.exportCache = ExportCache() self.exportCache.finish.connect(self.exportFinish) self.exportTip = ExportTip() # ---- 定时器 ---- # 弹幕机位置匹配 self.moveTimer = QTimer() self.moveTimer.timeout.connect(self.initTextPos) self.moveTimer.start(50) # 检查播放卡住的定时器 self.checkPlaying = QTimer() self.checkPlaying.timeout.connect(self.checkPlayStatus) # 最后再 resize 避免有变量尚未初始化 if resize: self.resize(resize[0], resize[1]) logging.info( f"{self.name_str} VLC 播放器构造完毕, 缓存大小: %dkb, 缓存路径: %s, 置顶?: %s, 启用弹幕?: %s" % (self.maxCacheSize, self.saveCachePath, self.top, self.startWithDanmu)) self.audioTimer = QTimer() self.audioTimer.timeout.connect(self.checkAudio) self.audioTimer.setInterval(100)