将iPhone视频转换为mp4并上传到PHP Server

时间:2017-12-29 02:10:36

标签: ios swift video

我有一个成功记录并将文件上传到我的PHP服务器的应用程序,遗憾的是该文件无法播放。我收到了指导,我需要使用AVAssetExportSession将文件转换为mp4以使其正常工作,但我无法正确地将其合并到我的代码中。我收到了错误

  

错误域= AVFoundationErrorDomain代码= -11823“无法保存”   UserInfo = {NSLocalizedRecoverySuggestion =再次尝试保存。,   NSLocalizedDescription =无法保存,NSUnderlyingError = 0x1d465ea50   {错误域= NSOSStatusErrorDomain代码= -12101“(null)”}}

这是我的代码:

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    print("Got a video")

    if let pickedVideo:URL = (info[UIImagePickerControllerMediaURL] as? URL) {
        // Save video to the main photo album
        let selectorToCall = #selector(CameraVideoViewController.videoWasSavedSuccessfully(_:didFinishSavingWithError:context:))
        UISaveVideoAtPathToSavedPhotosAlbum(pickedVideo.relativePath, self, selectorToCall, nil)
        imageSelected = true
        uuid = UUID().uuidString

        if imageSelected == true {
            saveFileName = "video-\(uuid).mp4"
        }
        // Save the video to the app directory so we can play it later
        let videoData = try? Data(contentsOf: pickedVideo)
        let paths = NSSearchPathForDirectoriesInDomains(
            FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        let documentsDirectory: URL = URL(fileURLWithPath: paths[0])
        let dataPath = documentsDirectory.appendingPathComponent(saveFileName)
        try! videoData?.write(to: dataPath, options: [])
        print("Saved to " + dataPath.absoluteString)

        imagePicker.dismiss(animated: true, completion: {
            // Anything you want to happen when the user saves an video
            self.encodeVideo(dataPath: dataPath)
            self.uploadVideo(videoData!)



        })
    } }


// custom body of HTTP request to upload image file
func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, videoData: Data, boundary: String) -> Data {

    let body = NSMutableData();

    if parameters != nil {
        for (key, value) in parameters! {
            body.appendString("--\(boundary)\r\n")
            body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
            body.appendString("\(value)\r\n")
        }
    }


    // if file is not selected, it will not upload a file to server, because we did not declare a name file
    var filename = ""

    if imageSelected == true {
        filename = "video-\(uuid).mp4"
    }


    let mimetype = "video/mp4"

    body.appendString("--\(boundary)\r\n")
    body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
    body.appendString("Content-Type: \(mimetype)\r\n\r\n")
    body.append(videoData)
    body.appendString("\r\n")

    body.appendString("--\(boundary)--\r\n")

    return body as Data

}    

//文件转换

func encodeVideo(dataPath: URL){
    let avAsset = AVURLAsset(url: dataPath)
    let startDate = Date()
    let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)

    let docDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    let myDocPath = NSURL(fileURLWithPath: docDir).appendingPathComponent("temp.mp4")?.absoluteString

    let docDir2 = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] as NSURL

    let filePath = docDir2.appendingPathComponent("rendered-Video.mp4")
    //uploadVideo(filePath)

    //deleteFile(filePath!)


    if FileManager.default.fileExists(atPath: myDocPath!){
        do{
            try FileManager.default.removeItem(atPath: myDocPath!)

        }catch let error{
            print(error)
        }
    }
    //self.uploadVideo((myDocPath as AnyObject) as! URL)

    exportSession?.outputURL = filePath
    exportSession?.outputFileType = AVFileType.mp4
    exportSession?.shouldOptimizeForNetworkUse = true

    let start = CMTimeMakeWithSeconds(0.0, 0)
    let range = CMTimeRange(start: start, duration: avAsset.duration)
    exportSession?.timeRange = range

    exportSession!.exportAsynchronously{() -> Void in
        switch exportSession!.status{
        case .failed:
            print("\(exportSession!.error!)")
        case .cancelled:
            print("Export cancelled")
        case .completed:
            let endDate = Date()
            let time = endDate.timeIntervalSince(startDate)
            print(time)
            print("Successful")
            print(exportSession?.outputURL ?? "")
        default:
            break
        }

    }
}

//文件上传

func uploadVideo(_ videoData: Data) {
    func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, videoData: Data, boundary: String) -> Data {

        let body = NSMutableData();

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }
        var filename = ""

        if imageSelected == true {
            filename = "video-\(uuid).mp4"
        }


        let mimetype = "video/mp4"
        body.append("--\(boundary)\r\n".data(using: String.Encoding.utf8)!)
        body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString(String(describing: "Content-Type: \(mimetype)\r\n\r\n".data(using: String.Encoding.utf8)))
        body.append(videoData)
        body.append(String(format: "\r\n").data(using: String.Encoding.utf8)!)

        body.append("--\(boundary)--\r\n".data(using: String.Encoding.utf8)!)

        return body as Data

    }
    let id = user!["id"] as! String
    uuid = UUID().uuidString


    let url = URL(string: "http://www.foo.com/videoposts.php")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"

    let param = [
        "id" : id,
        "uuid" : uuid
    ]

    // body
    let boundary = "Boundary-\(UUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

    // if picture is selected, compress it by half
    let imageData = Data()


    // ... body
    request.httpBody = createBodyWithParams(param, filePathKey: "file", videoData: imageData, boundary: boundary)

    // launch session
    URLSession.shared.dataTask(with: request) { data, response, error in

        // get main queu to communicate back to user
        DispatchQueue.main.async(execute: {


            if error == nil {

                do {

                    // json containes $returnArray from php
                    let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                    // declare new var to store json inf
                    guard let parseJSON = json else {
                        print("Error while parsing")
                        return
                    }

                    // get message from $returnArray["message"]
                    let message = parseJSON["message"]

                    // if there is some message - post is made
                    if message != nil {

                        // reset UI

                        self.postBtn.alpha = 0.4
                        self.imageSelected = false

                        // switch to another scene
                        self.tabBarController?.selectedIndex = 4

                    }

                } catch {

                    // get main queue to communicate back to user
                    DispatchQueue.main.async(execute: {
                        let message = "\(error)"
                        appDelegate.infoView(message: message, color: colorSmoothRed)
                    })
                    return

                }

            } else {

                // get main queue to communicate back to user
                DispatchQueue.main.async(execute: {
                    let message = error!.localizedDescription
                    appDelegate.infoView(message: message, color: colorSmoothRed)
                })
                return

            }


        })

        }.resume()

}

1 个答案:

答案 0 :(得分:0)

尝试检查要保存到的目录中是否已经存在某些文件。您可以添加以下代码。

do { // delete old video
        try FileManager.default.removeItem(at: savePathUrl)
    } catch { print(error.localizedDescription) }