如何通过Flask服务器在Flutter GUI中实现摄像头流?代码无画面求助
Flask摄像头流在Flutter中无法显示的排查与解决建议
我想在Flutter界面中查看Flask服务器推送的摄像头流,但当前代码没有画面显示,已确认服务器正在发送图片/流,求排查方向和解决办法,原代码如下:
Flask服务器代码
from flask import Flask, render_template, Response import cv2 import time app = Flask(__name__) def generate_frames(): cap = cv2.VideoCapture(0) while True: success, frame = cap.read() if not success: break else: ret, buffer = cv2.imencode('.jpg', frame) frame = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n') # 等待5秒后发送下一张图片 time.sleep(5) @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') if __name__ == '__main__': app.run(debug=True)
Flutter客户端代码
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:typed_data'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('Webcam Viewer'), ), body: WebcamView(), ), ); } } class WebcamView extends StatefulWidget { @override _WebcamViewState createState() => _WebcamViewState(); } class _WebcamViewState extends State<WebcamView> { String imageUrl = 'http://127.0.0.1:5000/video_feed'; @override Widget build(BuildContext context) { return Center( child: Image.network(imageUrl), ); } }
排查与解决建议
网络连通性与跨域问题
- 若使用真机测试,
127.0.0.1指向设备自身,需替换为电脑的局域网IP(如http://192.168.1.100:5000/video_feed) - Flask默认拦截跨域请求,需安装
flask-cors并配置:from flask_cors import CORS app = Flask(__name__) CORS(app) # 生产环境可指定允许的域名
- 若使用真机测试,
Flutter Image.network兼容性问题
Image.network对multipart/x-mixed-replace流的支持不稳定,建议改用定时请求+手动更新图片的方式:import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:typed_data'; import 'dart:async'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Webcam Viewer')), body: WebcamView(), ), ); } } class WebcamView extends StatefulWidget { @override _WebcamViewState createState() => _WebcamViewState(); } class _WebcamViewState extends State<WebcamView> { Uint8List? _imageBytes; late Timer _refreshTimer; final String _streamUrl = 'http://192.168.1.100:5000/video_feed'; // 替换为实际IP @override void initState() { super.initState(); _fetchFrame(); // 和服务器的5秒间隔同步 _refreshTimer = Timer.periodic(Duration(seconds: 5), (_) => _fetchFrame()); } Future<void> _fetchFrame() async { try { final response = await http.get(Uri.parse(_streamUrl)); if (response.statusCode == 200) { setState(() => _imageBytes = response.bodyBytes); } } catch (e) { print('获取帧失败: $e'); } } @override void dispose() { _refreshTimer.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Center( child: _imageBytes != null ? Image.memory(_imageBytes!) : CircularProgressIndicator(), ); } }
Flask流格式与性能问题
- 确认
yield中的--frame和响应头的boundary=frame完全一致,避免格式不匹配 - 先注释掉
time.sleep(5)测试,排除长间隔导致的超时问题
- 确认
权限配置
- 电脑端:确保Python程序已获得摄像头访问权限
- Flutter端:
- Android:在
AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET"/> - iOS:在
Info.plist中添加允许HTTP请求的配置,避免ATS拦截:<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
- Android:在
内容的提问来源于stack exchange,提问作者Adam Ghan
相关产品推荐
相关产品推荐

