在我的 iOS 应用程序中与我的外部附件通信以播放流中的视频
Posted
技术标签:
【中文标题】在我的 iOS 应用程序中与我的外部附件通信以播放流中的视频【英文标题】:In my iOS app to communicate with my external accessory to play video from stream 【发布时间】:2019-10-01 08:54:38 【问题描述】:在我的 ios 应用程序中,我需要使用外部附件框架播放视频。该框架将通过委托方法提供流。但我找不到从字节流播放的播放器。请推荐解决此问题的最佳方法
(void)stream:(NSStream*)theStream 句柄事件:(NSStreamEvent)streamEvent【问题讨论】:
“vupoint”已经在商店中提供了一个类似的项目。他们正在使用通过 Lightning 端口连接的外部摄像头。他们是如何工作的任何想法?? 【参考方案1】:有两种方法,第一种是将字节流保存在本地临时文件中,然后用 AVAsset 播放。
let url = URL(fileURLWithPath: filePath)
let asset = AVAsset(url: url)
let playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["playable"])
player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
playerLayer.videoGravity = .resizeAspect
view.layer.addSublayer(playerLayer)
如果您不想将视频保存在设备中,您可以在您的应用程序中创建一个 HTTPServer 并使用 AVURLAsset 与 AVPlayer 一起播放它。这是一个使用 GCD Web 服务器的示例,请注意服务器需要接受范围请求才能完美地与 AVPlayer 和 .
self.webServer = GCDWebServer()
self.webServer!.addDefaultHandler(forMethod: "GET", request: GCDWebServerRequest.self, asyncProcessBlock: (request,completionBlock) in
let path = Bundle.main.path(forResource: "sample", ofType: "mp4")
var attr:[FileAttributeKey : Any]
do
attr = try FileManager.default.attributesOfItem(atPath: path!)
catch
completionBlock(GCDWebServerResponse(statusCode: 500))
return
let fileSize = attr[FileAttributeKey.size] as! UInt64
if (request.hasByteRange())
let handler = FileHandle.init(forReadingAtPath: path!)
handler?.seek(toFileOffset: UInt64(request.byteRange.lowerBound))
var response:GCDWebServerDataResponse
if(request.byteRange.upperBound <= -1)
response = GCDWebServerDataResponse(data: (handler?.readDataToEndOfFile())!, contentType: "video/mp4")
else
response = GCDWebServerDataResponse(data: (handler?.readData(ofLength: request.byteRange.length))!, contentType: "video/mp4")
response.statusCode = 206
response.setValue("bytes \(request.byteRange.lowerBound)-\(request.byteRange.upperBound-1)/\(fileSize)", forAdditionalHeader: "Content-Range")
response.setValue("bytes", forAdditionalHeader: "Accept-Ranges")
response.setValue("\(request.byteRange.length)", forAdditionalHeader: "Content-Length")
response.setValue("video/mp4", forAdditionalHeader: "Content-Type")
response.setValue("keep-alive", forAdditionalHeader: "Connection")
completionBlock(response)
return
else
let handler = FileHandle.init(forReadingAtPath: path!)
let response = GCDWebServerDataResponse(data: (handler?.readDataToEndOfFile())!, contentType: "video/mp4")
response.setValue("bytes", forAdditionalHeader: "Accept-Ranges")
response.setValue("keep-alive", forAdditionalHeader: "Connection")
completionBlock(response)
return
)
self.webServer!.start(withPort: 8080, bonjourName: "")
GCDWebServer.setLogLevel(0)
然后您可以将您的 AVPlayer 设置为使用本地 Web 服务器来播放视频。
let asset = AVURLAsset(url: URL(string: "http://localhost:8080/")!)
let playerItem = AVPlayerItem(asset: asset, automaticallyLoadedAssetKeys: ["playable"])
player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x: 0, y: 0, width: viewPlayer.frame.width, height: viewPlayer.frame.height)
playerLayer.videoGravity = .resizeAspect
viewPlayer.layer.addSublayer(playerLayer)
self.view.layoutIfNeeded()
player!.play()
【讨论】:
感谢您的回复。这里连续将视频流保存到文件夹并从文件夹中播放会导致内存崩溃,因为它是直播流。? 我更新了答案,在示例中您只需要更改外部附件提供给您的文件管理器源字节。 感谢支持!!!。但是上面的代码仅适用于单个请求。在这里,我们必须保持连接直到流结束。 Get 请求仅调用一次,服务器提供的完整数据一次。就我而言,需要附加流/数据,并且应该始终由服务器提供服务。文件大小我们无法提前提供。它随着时间的推移而增加。以上是关于在我的 iOS 应用程序中与我的外部附件通信以播放流中的视频的主要内容,如果未能解决你的问题,请参考以下文章
无法在 iOS 中与 iPodMusicPlayer 捆绑播放歌曲
如何让键盘在我的 UITableView 中与我的 UITextField 一起显示?
如何在我的 iOS 模拟器上自动安装自定义 CA 根证书以进行测试?