托管--> PythonAnywhere
工作:服务器从客户端接收图像并将其更新到网页。另一个客户端访问该网页并可以看到视频流。服务器不保存图像,它只是在接收图像时将其显示在网页上。
问题-->图像上传到服务器是顺利的,但只要我打开网页,从客户端上传的图像停止。如果有人访问网页,服务器无法接收图像
服务器代码
from flask import Flask, Response, render_template
from flask import request
import cv2
import numpy as np
app = Flask(__name__)
global current_frame
current_frame = None
def generate_frames():
while True:
if current_frame is not None:
ret, buffer = cv2.imencode('.jpg', current_frame)
if ret:
frame_bytes = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
@app.route('/')
def index():
return render_template('index.html')
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/upload_frame', methods=['POST'])
def upload_frame():
global current_frame
frame = request.data
nparr = np.fromstring(frame, np.uint8)
current_frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
return "Frame received and displayed"
if __name__ == '__main__':
app.run('0.0.0.0')
字符串
客户端代码
import cv2
import requests
import numpy as np
import time
server_url = "http://danial880.pythonanywhere.com/upload_frame"
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
print("Failed to capture frame")
break
_, buffer = cv2.imencode('.jpg', frame)
frame_bytes = buffer.tobytes()
try:
# Send the frame to the server
response = requests.post(server_url, data=frame_bytes, headers={"Content-Type": "image/jpeg"})
if response.status_code == 200:
print("Frame uploaded successfully")
else:
print(f"Frame upload failed with status code {response.status_code}")
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
#cv2.imshow("Webcam Feed", frame)
time.sleep(0.1)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
型
我尝试的解决方案:使服务器异步
from flask import Flask, Response, render_template
from flask import request
import cv2
import numpy as np
import asyncio
app = Flask(__name__)
global current_frame
current_frame = None
async def generate_frames():
while True:
if current_frame is not None:
ret, buffer = cv2.imencode('.jpg', current_frame)
if ret:
frame_bytes = buffer.tobytes()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
await asyncio.sleep(0.01) # Add a small delay to reduce CPU load
@app.route('/')
def index():
return render_template('index.html')
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
@app.route('/upload_frame', methods=['POST'])
async def upload_frame():
global current_frame
frame = request.data
nparr = np.fromstring(frame, np.uint8)
current_frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
return "Frame received and displayed"
if __name__ == '__main__':
app.run()
型
但是在异步服务器之后,网页上没有显示任何图像。简单服务器显示的是收到的最后一帧。
我可以对服务器进行什么更改,以便我可以有一个流畅的流。
2条答案
按热度按时间okxuctiv1#
如果Flask太慢,为了测试,尝试其他处理并发请求的解决方案,如Eventlet(
pip install eventlet
)或Gevent(pip install gevent
),并对标准库进行monkey-patch以使其成为非阻塞的。对于Eventlet(使用
monkey_patch
):字符串
对于Gevent(使用
atch_all
):型
使用猴子补丁提高了流媒体速度,但不是很流畅。我在AWS LightSale上尝试过相同的服务器代码。还有其他方法可以改进吗?
如果使用Monkey修补程序后流媒体性能有所改善,但仍然不完全流畅,您可以尝试:
cv2.imencode
中调整JPEG压缩级别,以在质量和性能之间找到平衡。-限制客户端捕获和服务器发送端的帧速率,以减少工作量。以下是如何实现帧速率限制和分辨率降低的示例:
型
如果服务器从多个客户端接收请求,请考虑实施负载平衡。在AWS上,可以使用Elastic Load Balancing进行管理。
也可以尝试使用profile your server's performance来识别瓶颈。像用于CPU分析的
cProfile
和用于内存使用的memory_profiler
这样的工具可以提供帮助。请记住,网络速度和延迟可能是一个因素,特别是在涉及不同地理区域的情况下。与PythonAnywhere相比,AWS LightSail应该提供更好的网络性能,特别是如果您选择更靠近客户端的区域。
尝试不同配置的Web服务器和WSGI容器,如Gunicorn或uWSGI与Nginx。这些服务器更能够处理并发连接,并且可以进行性能微调。
还可以考虑使用WebSocket在客户端和服务器之间建立持久连接,这更适合于实时数据传输。
jrcvhitl2#
您无法在PythonAnywhere Web应用程序中运行异步代码。