flask 服务器在 Raspberry pi 视频流上崩溃

问题描述 投票:0回答:1

我使用 RPI4 构建了一辆 pi 汽车,它使用 Flask 服务器将网络摄像头的视频流传输到我的电脑,并且它也由我的电脑控制。但有时,当我在车上快速行驶时,摄像头有时会冻结,当我尝试再次连接到视频源时,会出现一个名为“内部服务器错误”的错误。这可能是由于内部错误或服务器故障造成的。超载”。这是在 pi 上运行的服务器端脚本

from gpiozero import Motor, Servo, Device
from gpiozero.pins.pigpio import PiGPIOFactory
import socket
from flask import Flask, Response
import cv2
from imutils.video import VideoStream
import threading

# Flask app for streaming video
app = Flask(__name__)

# Setup for GPIO
Device.pin_factory = PiGPIOFactory()

# Initialize the motors and servo
motor_left = Motor(forward=6, backward=13)
motor_right = Motor(forward=19, backward=26)
servo = Servo(18)

# Video stream initialization
vs = VideoStream(src=0).start()

def generate():
    """Video streaming generator function with optimizations."""
    while True:
        frame = vs.read()
        # Resize the frame to reduce size
        frame = cv2.resize(frame, (540, 380))  # Example resize, adjust as needed
        
        # Convert the frame to grayscale to reduce size further (optional)
        # frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        
        # Adjust JPEG quality to reduce size
        ret, jpeg = cv2.imencode('.jpg', frame, [int(cv2.IMWRITE_JPEG_QUALITY), 50])
        
        if not ret:
            continue
        
        yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + jpeg.tobytes() + b'\r\n')

@app.route('/video_feed')
def video_feed():
    """Video streaming route."""
    return Response(generate(), mimetype='multipart/x-mixed-replace; boundary=frame')

# Thread to run the Flask app
def run_flask_app():
    app.run(host='0.0.0.0', port=5000, debug=False, threaded=True, use_reloader=False)

flask_thread = threading.Thread(target=run_flask_app)
flask_thread.start()

# Rest of your GPIO control code
# Motor control functions
def forward():
    motor_left.forward()
    motor_right.forward()

def backward():
    motor_left.backward()
    motor_right.backward()

def right():
    motor_left.backward()
    motor_right.forward()

def left():
    motor_left.forward()
    motor_right.backward()

def stop():
    motor_left.stop()
    motor_right.stop()

# Updated servo control functions
def servo_move_left():
    servo.max()

def servo_move_right():
    servo.min()

def servo_stop():
    # Updated to explicitly set servo to neutral position
    servo.value = 0  # Neutral position

# Command mapping with added 'servo_neutral' command
commands = {
    "forward": forward,
    "backward": backward,
    "left": left,
    "right": right,
    "stop": stop,
    "servo_move_left": servo_move_left,
    "servo_move_right": servo_move_right,
    "servo_neutral": servo_stop,  # Use "servo_neutral" to center the servo
}

def execute_command(command):
    action = commands.get(command)
    if action:
        action()
    else:
        print(f"Unknown command: {command}")

def main():
    host = '0.0.0.0'
    port = 12345

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((host, port))
        s.listen()
        print("Server listening on port", port)

        while True:
            conn, addr = s.accept()
            with conn:
                print(f"Connected by {addr}")
                while True:
                    data = conn.recv(1024)
                    if not data:
                        break
                    command = data.decode('utf-8').strip().lower()
                    execute_command(command)


if __name__ == "__main__":
    main()

以及用于控制它的PC端代码

import socket
import tkinter as tk
import webbrowser


def send_command(command):
    """Send command to the Raspberry Pi server."""
    try:
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.connect(("192.168.1.44", 12345))  # Update with your Raspberry Pi's IP address
            s.sendall(command.encode())
    except Exception as e:
        print(f"Error sending command: {e}")

def open_video_stream():
    """Open the video stream in the default web browser."""
    stream_url = "http://192.168.1.44:5000/video_feed"  # Update with your Raspberry Pi's IP address
    webbrowser.open(stream_url)

def on_key_press(event):
    """Map key presses to movement commands."""
    commands = {
        'w': 'forward',
        's': 'backward',
        'a': 'left',
        'd': 'right',
        'Left': 'servo_move_left',  # Arrow keys for servo movement
        'Right': 'servo_move_right',
        'Up': 'servo_neutral',  # Additional key for setting servo to neutral
    }
    command = commands.get(event.keysym) or commands.get(event.char)  # Handle both special keys and char keys
    if command:
        send_command(command)

def on_key_release(event):
    """Handle key release events to stop the car and potentially the servo."""
    control_keys = ['w', 's', 'a', 'd', 'Left', 'Right']
    if event.keysym in control_keys:
        send_command('stop')  # Stops the car and servo movement on release of movement keys

root = tk.Tk()
root.title("Raspberry Pi Car and Servo Control")

# Add a button to open the video stream
stream_button = tk.Button(root, text="Open Video Stream", command=open_video_stream)
stream_button.pack(pady=20)

# Bind key press and release events
root.bind("<KeyPress>", on_key_press)
root.bind("<KeyRelease>", on_key_release)

# Instructions for the user
instructions = tk.Label(root, text="Use WASD for car control, Arrow keys for servo movement, and 'Up' for servo neutral.\nReleasing control keys stops movement.\nPress 'Open Video Stream' to view the camera.")
instructions.pack(pady=20)

root.mainloop()

请问谁能帮忙解决这个问题吗?

我尝试通过放慢速度并降低流质量来减少负载,但它没有解决问题。

python flask raspberry-pi4
1个回答
0
投票

当图片中涉及硬件时,很难预测行为并识别有缺陷的部件。

您需要从基本的故障排除步骤开始,例如检查硬件连接和监控系统资源。根据您的代码尝试处理以下部分..

限制帧速率

vs = VideoStream(src=0, framerate=20).start()

您仍然感觉提要更粗,设置更低的帧速率

减少 Flask 线程池大小

你可以尝试类似的事情

app.run(host='0.0.0.0', port=5000, debug=False, threaded=True, use_reloader=False)

您还可以尝试关闭视频流。这将确保在 Flask 服务器停止时正确停止并清理视频流

@app.route('/video_feed')
def video_feed():
    """Video streaming route."""
    try:
        return Response(generate(), mimetype='multipart/x-mixed-replace; boundary=frame')
    except Exception as e:
        print(f"Error streaming video: {e}")
        return Response(status=500)

# Close Video Stream on Flask Shutdown
@app.teardown_appcontext
def close_video_stream(exception=None):
    vs.stop()
© www.soinside.com 2019 - 2024. All rights reserved.