在我的 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 根证书以进行测试?

在我的 Java 应用程序中与贝宝服务器通信时出现 ssl 握手错误

如何设置正确的 Ruby 版本以在 Aptana 3 中与我的 Rails 5 项目一起使用?