如何在iOS应用中捕获Flask实现的树莓派摄像头直播流?
嘿,看起来你已经搞定了树莓派端的直播流,要在iOS App里实现观看的话,有几个实用的方案,我给你详细说说:
方案1:用WKWebView直接复用现有网页(最省事)
这是最快实现的方式——既然你已经有了可以正常访问的网页端,直接在iOS App里用WKWebView加载这个网页就行,完全不需要修改后端代码,也不用自己处理流解析。
示例代码:
import UIKit import WebKit class StreamWebViewController: UIViewController, WKUIDelegate { private var webView: WKWebView! override func loadView() { let webConfig = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: webConfig) webView.uiDelegate = self view = webView } override func viewDidLoad() { super.viewDidLoad() guard let streamURL = URL(string: "http://192.168.0.241:7070") else { return } webView.load(URLRequest(url: streamURL)) } }
这个方案的优势是零学习成本,直接复用现有资源,适合快速验证需求。
方案2:原生解析multipart/x-mixed-replace流
如果不想用WebView,想自己控制帧渲染逻辑,可以直接请求你的/video_feed接口,手动解析这个多部分JPEG流,把每帧转成UIImage显示。
核心思路是:用URLSession获取流数据,按--frame边界分割出每个JPEG帧,再转成图片更新UI(注意必须在主线程更新UI)。
示例代码(核心部分):
import UIKit class NativeStreamViewController: UIViewController { @IBOutlet weak var streamImageView: UIImageView! private var urlSession: URLSession? private var dataTask: URLSessionDataTask? private var accumulatedData = Data() override func viewDidLoad() { super.viewDidLoad() startStreaming() } private func startStreaming() { guard let streamURL = URL(string: "http://192.168.0.241:7070/video_feed") else { return } let config = URLSessionConfiguration.default urlSession = URLSession(configuration: config, delegate: self, delegateQueue: nil) dataTask = urlSession?.dataTask(with: streamURL) dataTask?.resume() } } extension NativeStreamViewController: URLSessionDataDelegate { func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) { accumulatedData.append(data) let boundary = "--frame\r\n".data(using: .utf8)! // 分割所有完整的帧 while let boundaryIndex = accumulatedData.range(of: boundary)?.lowerBound { let frameData = accumulatedData[..<boundaryIndex] accumulatedData.removeSubrange(...boundaryIndex) // 提取JPEG数据(跳过Content-Type头) if let headerEnd = frameData.range(of: "\r\n\r\n".data(using: .utf8)!)?.upperBound { let jpegData = frameData[headerEnd...] DispatchQueue.main.async { self.streamImageView.image = UIImage(data: Data(jpegData)) } } } } }
注意:实际使用时需要处理更复杂的边界情况(比如不完整的帧数据),但这个示例已经能实现基础的流渲染。
方案3:转成iOS友好的HLS流(进阶优化)
如果想要更好的播放体验(比如缓存、帧率自适应、播放控制),可以把后端的流转成HLS格式——iOS的AVPlayer原生支持HLS,体验比前面两种方案更流畅。
步骤1:后端用FFmpeg转流
在树莓派上安装FFmpeg,然后执行命令把摄像头流转成HLS:
ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -preset ultrafast -f hls -hls_time 2 -hls_list_size 5 /path/to/your/flask/static/stream.m3u8
这个命令会生成stream.m3u8和对应的分片文件,放在Flask的static目录下。
步骤2:iOS端用AVPlayer播放
import UIKit import AVKit class HLSPlayerViewController: UIViewController { private var player: AVPlayer! private var playerLayer: AVPlayerLayer! override func viewDidLoad() { super.viewDidLoad() guard let hlsURL = URL(string: "http://192.168.0.241:7070/static/stream.m3u8") else { return } player = AVPlayer(url: hlsURL) playerLayer = AVPlayerLayer(player: player) playerLayer.frame = view.bounds view.layer.addSublayer(playerLayer) player.play() } }
这个方案的优势是播放体验更稳定,还能轻松添加暂停、进度条等控制功能,但需要额外配置后端的转流工具。
内容的提问来源于stack exchange,提问作者gawron103
相关产品推荐
相关产品推荐

