Files
meetingroom-netscreen/push_screen.py

209 lines
8.1 KiB
Python
Raw Normal View History

import subprocess
import psutil
import os
import sys
import socket
import time
from loguru import logger
from PySide6.QtWidgets import (QApplication, QMainWindow, QPushButton, QMessageBox,
QVBoxLayout, QWidget, QLabel, QGroupBox, QGridLayout,
QStatusBar, QProgressBar, QFrame)
from PySide6.QtCore import QTimer, Qt, QThread, Signal
from PySide6.QtGui import QFont, QPalette, QColor
logger.add(sys.stderr, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", level="INFO")
SERVER_IP = "192.168.1.100"
MEDIAMTX_PATH = r"D:\ScreenCast\mediamtx\mediamtx.exe"
FFMPEG_PATH = r"D:\ScreenCast\ffmpeg\bin\ffmpeg.exe"
STREAM_PATH = "screen"
class ConnectionChecker(QThread):
status_update = Signal(dict)
def run(self):
while True:
status = {
"mediamtx": self.check_mediamtx(),
"ffmpeg": self.check_ffmpeg(),
"server": self.check_server(),
"server_port": self.check_port(SERVER_IP, 8554),
}
self.status_update.emit(status)
time.sleep(3)
def check_mediamtx(self):
for proc in psutil.process_iter(['name']):
if proc.info['name'] == 'mediamtx.exe':
return True
return False
def check_ffmpeg(self):
return os.path.exists(FFMPEG_PATH)
def check_server(self):
try:
socket.create_connection((SERVER_IP, 8554), timeout=2)
return True
except:
return False
def check_port(self, ip, port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
result = sock.connect_ex((ip, port))
sock.close()
return result == 0
except:
return False
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("投屏源控制")
self.setFixedSize(500, 350)
self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar)
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout(central_widget)
title_label = QLabel("会议投屏系统 - 主播端")
title_font = QFont("Microsoft YaHei", 14, QFont.Bold)
title_label.setFont(title_font)
title_label.setAlignment(Qt.AlignCenter)
main_layout.addWidget(title_label)
config_group = QGroupBox("本地配置")
config_layout = QGridLayout()
self.mediamtx_label = QLabel("MediaMTX: 未检测")
self.ffmpeg_label = QLabel("FFmpeg: 未检测")
self.server_label = QLabel("服务器连接: 未检测")
self.port_label = QLabel("RTSP端口: 未检测")
self.mediamtx_indicator = QLabel("")
self.mediamtx_indicator.setFixedWidth(20)
self.ffmpeg_indicator = QLabel("")
self.ffmpeg_indicator.setFixedWidth(20)
self.server_indicator = QLabel("")
self.server_indicator.setFixedWidth(20)
self.port_indicator = QLabel("")
self.port_indicator.setFixedWidth(20)
config_layout.addWidget(self.mediamtx_indicator, 0, 0)
config_layout.addWidget(self.mediamtx_label, 0, 1)
config_layout.addWidget(self.ffmpeg_indicator, 1, 0)
config_layout.addWidget(self.ffmpeg_label, 1, 1)
config_layout.addWidget(self.server_indicator, 2, 0)
config_layout.addWidget(self.server_label, 2, 1)
config_layout.addWidget(self.port_indicator, 3, 0)
config_layout.addWidget(self.port_label, 3, 1)
config_group.setLayout(config_layout)
main_layout.addWidget(config_group)
info_group = QGroupBox("流信息")
info_layout = QGridLayout()
info_layout.addWidget(QLabel("服务器IP:"), 0, 0)
info_layout.addWidget(QLabel(SERVER_IP), 0, 1)
info_layout.addWidget(QLabel("推流地址:"), 1, 0)
info_layout.addWidget(QLabel(f"rtsp://{SERVER_IP}:8554/{STREAM_PATH}"), 1, 1)
info_layout.addWidget(QLabel("访问地址:"), 2, 0)
info_layout.addWidget(QLabel(f"http://{SERVER_IP}:8889/webrtc.html?src=screen"), 2, 1)
info_group.setLayout(info_layout)
main_layout.addWidget(info_group)
self.btn_push = QPushButton("🎬 开始全屏投屏")
self.btn_push.setFixedHeight(50)
self.btn_push.setFont(QFont("Microsoft YaHei", 11))
self.btn_push.clicked.connect(self.push_full_screen)
main_layout.addWidget(self.btn_push)
self.log_label = QLabel("日志: 等待启动...")
self.log_label.setWordWrap(True)
self.log_label.setFrameShape(QFrame.Shape.StyledPanel)
self.log_label.setFixedHeight(40)
main_layout.addWidget(self.log_label)
self.checker = ConnectionChecker()
self.checker.status_update.connect(self.update_status)
self.checker.start()
logger.info("投屏源控制界面已初始化")
def update_status(self, status):
if status["mediamtx"]:
self.mediamtx_indicator.setStyleSheet("color: green; font-size: 16px;")
self.mediamtx_label.setText(f"MediaMTX: ✓ 运行中")
else:
self.mediamtx_indicator.setStyleSheet("color: red; font-size: 16px;")
self.mediamtx_label.setText(f"MediaMTX: ✗ 未运行")
if status["ffmpeg"]:
self.ffmpeg_indicator.setStyleSheet("color: green; font-size: 16px;")
self.ffmpeg_label.setText(f"FFmpeg: ✓ 已安装")
else:
self.ffmpeg_indicator.setStyleSheet("color: red; font-size: 16px;")
self.ffmpeg_label.setText(f"FFmpeg: ✗ 未找到")
if status["server"]:
self.server_indicator.setStyleSheet("color: green; font-size: 16px;")
self.server_label.setText(f"服务器连接: ✓ 可连接")
else:
self.server_indicator.setStyleSheet("color: orange; font-size: 16px;")
self.server_label.setText(f"服务器连接: ✗ 连接失败")
if status["server_port"]:
self.port_indicator.setStyleSheet("color: green; font-size: 16px;")
self.port_label.setText(f"RTSP端口: ✓ 端口开放")
else:
self.port_indicator.setStyleSheet("color: orange; font-size: 16px;")
self.port_label.setText(f"RTSP端口: ✗ 端口关闭")
def start_mediamtx(self):
if not self.checker.check_mediamtx():
logger.info("启动MediaMTX服务")
subprocess.Popen([MEDIAMTX_PATH], cwd=r"D:\ScreenCast\mediamtx", creationflags=subprocess.CREATE_NEW_CONSOLE)
time.sleep(3)
logger.info("MediaMTX服务已启动")
self.log_label.setText("日志: MediaMTX服务已启动")
else:
logger.info("MediaMTX已在运行")
self.log_label.setText("日志: MediaMTX已在运行")
def push_full_screen(self):
logger.info("开始全屏投屏")
self.start_mediamtx()
if not os.path.exists(FFMPEG_PATH):
logger.error("FFmpeg未安装")
QMessageBox.warning(self, "错误", "FFmpeg未安装请检查配置")
return
cmd = [
FFMPEG_PATH,
"-f", "gdigrab", "-framerate", "30", "-i", "desktop",
"-c:v", "libx264", "-preset", "ultrafast", "-tune", "zerolatency",
"-f", "rtsp", f"rtsp://{SERVER_IP}:8554/{STREAM_PATH}"
]
logger.info(f"执行FFmpeg命令: {' '.join(cmd)}")
subprocess.Popen(cmd, creationflags=subprocess.CREATE_NEW_CONSOLE)
logger.info("FFmpeg推流已启动")
self.log_label.setText("日志: FFmpeg推流已启动正在向服务器推送...")
QMessageBox.information(self, "提示", f"全屏投屏已启动!\n\n接收端可打开浏览器访问:\nhttp://{SERVER_IP}:8889/webrtc.html?src=screen")
def closeEvent(self, event):
self.checker.terminate()
event.accept()
if __name__ == "__main__":
logger.info("应用程序启动")
app = QApplication(sys.argv)
app.setStyle("Fusion")
window = MainWindow()
window.show()
sys.exit(app.exec())