ios - 在我的 iOS 应用程序中与外部配件通信以播放流中的视频

标签 ios swift usb video-streaming external-accessory

在我的 iOS 应用程序中,我需要使用外部附件框架播放视频。该框架将通过委托(delegate)方法提供流。但我找不到从字节流播放的播放器。请推荐解决此问题的最佳方法

  • (void)流:(NSStream*)流句柄事件:(NSStreamEvent)streamEvent { }

最佳答案

有两种方法可以实现这一点,第一种是将字节流保存在本地临时文件中,然后使用 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 设置为使用本地网络服务器来播放视频。

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()

关于ios - 在我的 iOS 应用程序中与外部配件通信以播放流中的视频,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58181278/

相关文章:

ios - 将 NSManagedObject 变成部分错误,其中某些字段为零,有些字段不是

ios - AVPlayerViewController 问题

ios - 在 Mac 上通过 USB 访问 iOS 设备

windows - GetRawInputDeviceInfo 在 Windows XP 中返回错误的 USB HID 设备名称语法

IOS Swift 如何更快地返回标签响应

iOS JSON 解析错误

ios - 如何正确强制 MKMapView 以相同的缩放比例重绘 MKOverlayRenderer

ios - Firebase - 跨多个位置的原子写入不起作用

Swift - 如何在菜单栏应用程序中跨窗口共享类(作为单例)?

usb - WebUSB 和 WebSerial 之间的区别