rtsp
import sys import cv2 import numpy as np from PyQt5.QtCore import QThread, pyqtSignal, Qt from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton, QStatusBar, QSpinBox) import socket import threading class RTSPServer: def __init__(self, port=8554): self.port = port self.running = False self.frame = None self.lock = threading.Lock() def start(self): self.running = True threading.Thread(target=self._run_server, daemon=True).start() def _run_server(self): with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('0.0.0.0', self.port)) s.listen(1) while self.running: conn, addr = s.accept() threading.Thread(target=self._handle_client, args=(conn,)).start() def _handle_client(self, conn): try: conn.send(b'RTSP/1.0 200 OK\r\n') while self.running: with self.lock: if self.frame is not None: _, jpeg = cv2.imencode('.jpg', self.frame) data = jpeg.tobytes() header = f"Content-Length: {len(data)}\r\n\r\n".encode() conn.send(header + data) except Exception as e: print(f"Client error: {e}") finally: conn.close() def update_frame(self, frame): with self.lock: self.frame = frame def stop(self): self.running = False class CameraThread(QThread): frame_ready = pyqtSignal(np.ndarray) def __init__(self, src=0): super().__init__() self.cap = cv2.VideoCapture(src) self.running = False self.set_resolution(1280, 720) def set_resolution(self, width, height): self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) self.cap.set(cv2.CAP_PROP_FPS, 30) def run(self): self.running = True while self.running: ret, frame = self.cap.read() if ret: self.frame_ready.emit(frame) def stop(self): self.running = False self.wait() self.cap.release() class MainWindow(QMainWindow): def __init__(self): super().__init__() self.init_ui() self.init_camera() self.init_rtsp() def init_ui(self): self.setWindowTitle('USB摄像头RTSP服务') self.setGeometry(100, 100, 800, 600) central_widget = QWidget() self.setCentralWidget(central_widget) self.video_label = QLabel() self.video_label.setAlignment(Qt.AlignCenter) self.btn_start = QPushButton('启动服务') self.btn_stop = QPushButton('停止服务') self.port_spin = QSpinBox() self.port_spin.setRange(1024, 65535) self.port_spin.setValue(8554) layout = QVBoxLayout() layout.addWidget(self.video_label) layout.addWidget(QLabel("RTSP端口:")) layout.addWidget(self.port_spin) layout.addWidget(self.btn_start) layout.addWidget(self.btn_stop) central_widget.setLayout(layout) self.status_bar = QStatusBar() self.setStatusBar(self.status_bar) self.btn_start.clicked.connect(self.start_service) self.btn_stop.clicked.connect(self.stop_service) def init_camera(self): self.camera_thread = CameraThread(0) self.camera_thread.frame_ready.connect(self.process_frame) def init_rtsp(self): self.rtsp_server = RTSPServer() def process_frame(self, frame): rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb_frame.shape q_img = QImage(rgb_frame.data, w, h, ch * w, QImage.Format_RGB888) self.video_label.setPixmap( QPixmap.fromImage(q_img).scaled( self.video_label.width(), self.video_label.height(), Qt.KeepAspectRatio )) if hasattr(self, 'streaming') and self.streaming: self.rtsp_server.update_frame(frame) def start_service(self): self.rtsp_server.port = self.port_spin.value() self.rtsp_server.start() self.camera_thread.start() self.streaming = True self.status_bar.showMessage( f"RTSP服务已启动: rtsp://{socket.gethostbyname(socket.gethostname())}:{self.rtsp_server.port}" ) def stop_service(self): self.streaming = False self.rtsp_server.stop() self.camera_thread.stop() self.status_bar.showMessage("服务已停止") def closeEvent(self, event): self.stop_service() event.accept() if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
###############
QQ 3087438119

浙公网安备 33010602011771号