如何在 swift 中使用 cocoahttpserver 流式传输音频(设备歌曲)?

Posted

技术标签:

【中文标题】如何在 swift 中使用 cocoahttpserver 流式传输音频(设备歌曲)?【英文标题】:How to stream audio(Device Songs) using cocoahttpserver in swift? 【发布时间】:2017-05-03 09:36:59 【问题描述】:

我正在创建一个设备充当服务器并且其他设备加入的应用程序,我设法创建了服务器,但我找不到流式传输音频的方法(设备本地歌曲)。

步骤:

    我用 GCDWebServer 创建服务器

    从 MPMediaItem 获取 NSData

    在服务器默认获取请求中设置 songData

这是我的代码:

class DjSocketServer : NSObject,GCDWebServerDelegate

var myLocalServer = GCDWebServer()
var isRunning = false
var serverType = ServerType.isDj


func startServer(with type:ServerType)

    serverType = type
    GCDWebServer.setLogLevel(4)
    myLocalServer = GCDWebServer()

    myLocalServer?.delegate = self

    myLocalServer?.addDefaultHandler(forMethod: "GET", request: GCDWebServerRequest.self, processBlock: request in

        //Default Response to GET request
        if let requestUrl = request?.url.absoluteString
        
            if requestUrl.contains(".mp3")
            
                return GCDWebServerDataResponse(data: playerInfo.songPlayedData as Data!, contentType: "audio/mp3")
            
        

        let para:NSMutableDictionary = NSMutableDictionary()
        para.setValue(DjInformation.party_name, forKey: "djName")
        para.setValue(Common.DJ_Connected_Users.count, forKey: "listener")
        para.setValue(DjInformation.dj_ip, forKey: "djIp")
        para.setValue("http://\(DjInformation.dj_ip):\(AppConfig.Dj_Port)/atrist_poster", forKey: "djImg")
        para.setValue(DjInformation.artist_name, forKey: "artist")

        let jsonData = try! JSONSerialization.data(withJSONObject: para, options: JSONSerialization.WritingOptions.prettyPrinted)
        return GCDWebServerDataResponse(data: jsonData, contentType: "application/json")
    )

    //myLocalServer?.start(withPort: UInt(ServerPort.DjPort.rawValue), bonjourName: UIDevice.current.name)
    do
    
    try myLocalServer?.start(options: [GCDWebServerOption_AutomaticallySuspendInBackground:false,GCDWebServerOption_Port:UInt(ServerPort.DjPort.rawValue),GCDWebServerOption_BonjourName:UIDevice.current.name])
        print("\n\n\n\n\n\nSuccess Tag:Started ----- \n\n\n\n\n\n")
    catch
    
        print("Error Tag : Starting MainDj Server")
    


func webServerDidStart(_ server: GCDWebServer!) 
    print("Visit \(server.serverURL) in your web browser")
    isRunning = true


func webServerDidCompleteBonjourRegistration(_ server: GCDWebServer!) 
    print(" CompleteBonjourRegistration ")


func webServerDidStop(_ server: GCDWebServer!) 
    print("\n\n\n\n\n\n\nServer Stoped MainDj\n\n\n\n\n\n\n")
    isRunning = false


我将 MPMediaItem 传递给此函数并转换为 NSData

class func getSongRawData(item: MPMediaItem,success: @escaping (NSData) -> Void,fail: @escaping (NSError) -> Void) -> Void 

    if let exporter = createSongExporter(item: item) 
        exporter.exportAsynchronously(completionHandler:  () -> Void in
            switch exporter.status 
            case .completed:
                let rawData = NSData(contentsOf: exporter.outputURL!)!
                songUrl_selected = (exporter.outputURL?.absoluteString)!
                //print("UURL : ",exporter.outputURL?.absoluteString ?? "None")
                success(rawData)
            default:
                let e = NSError(
                    domain: "jp.co.faithcreates.Meowziq",
                    code: MusicManagerError.RawDataAccessFailed.rawValue,
                    userInfo: [
                        "exporterStatus": exporter.status.rawValue
                    ])
                fail(e)
            

            self.removeExportedFile(url: exporter.outputURL! as NSURL)
        )
     else 
        let e = NSError(
            domain: "jp.co.faithcreates.Meowziq",
            code: MusicManagerError.RawDataAccessFailed.rawValue,
            userInfo: nil
        )
        fail(e)
    


private class func createSongExporter(item: MPMediaItem) -> AVAssetExportSession? 
    if let url = item.assetURL 
        let asset = AVURLAsset(url: url, options: nil)
        let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A)

        exporter?.outputFileType = "com.apple.m4a-audio";

        let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let fileName = createExportFileName()
        exporter?.outputURL = NSURL(fileURLWithPath: docDir).appendingPathComponent(fileName)

        return exporter
     else 
        return nil
    


private class func createExportFileName() -> String 
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyyMMddhhmmss"
    let dateString = dateFormatter.string(from: NSDate() as Date)
    return String(format: "%@.m4a", dateString)
    //return String(format: "%@.m4a", "tmp")

【问题讨论】:

"流式传输音频(设备本地歌曲)" - 如果您想流式传输它们,它们不是本地歌曲吗?你能澄清你的问题和环境架构吗? @Lepidopteron local song 表示我音乐库的歌曲 谢谢。如果可能的话,您能否以使用代码访问这些问题的方式编辑您的问题)? 【参考方案1】:

将 NSData 保存为文档目录中的 mp3 文件,然后像下面这样使用 GCDWebServerFileResponse

let fileResponse = GCDWebServerFileResponse(file: song_filePath) 
return fileResponse

【讨论】:

以上是关于如何在 swift 中使用 cocoahttpserver 流式传输音频(设备歌曲)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 kotlin native 中使用 swift 库?

如何在 Swift 中使用 Apple 地图 - 你必须使用 C 还是 Swift 可以?

如何在 Swift 中使用 MKPolylineView

如何在 Swift 中使用`syslog`

如何在 swift 项目中使用 TPKeyboardAvoiding?

如何在 Playground 中使用 Swift 包管理器